[-]
[+]
|
Changed |
_service:tar_git:libhybris.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -1,7 +1,7 @@
<services>
<service name="tar_git">
- <param name="url">https://github.com/elros34/libhybris.git</param>
- <param name="branch">freezes2</param>
+ <param name="url">https://github.com/mer-hybris/libhybris.git</param>
+ <param name="branch">master</param>
<param name="revision">HEAD</param>
<param name="token"></param>
<param name="debian"></param>
|
[-]
[+]
|
Deleted |
_service:tar_git:libhybris-0.0.5.32+freezes2.20210712173613.14.g7e4240e.tar.bz2/libhybris/hybris/INSTALL
^
|
@@ -1,370 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
-Inc.
-
- Copying and distribution of this file, with or without modification,
-are permitted in any medium without royalty provided the copyright
-notice and this notice are preserved. This file is offered as-is,
-without warranty of any kind.
-
-Basic Installation
-==================
-
- Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package. The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package. Some packages provide this
-`INSTALL' file but do not implement all of the features documented
-below. The lack of an optional feature in a given package is not
-necessarily a bug. More recommendations for GNU packages can be found
-in *note Makefile Conventions: (standards)Makefile Conventions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
- The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system.
-
- Running `configure' might take a while. While running, it prints
- some messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package, generally using the just-built uninstalled binaries.
-
- 4. Type `make install' to install the programs and any data files and
- documentation. When installing into a prefix owned by root, it is
- recommended that the package be configured and built as a regular
- user, and only the `make install' phase executed with root
- privileges.
-
- 5. Optionally, type `make installcheck' to repeat any self-tests, but
- this time using the binaries in their final installed location.
- This target does not install anything. Running this target as a
- regular user, particularly if the prior `make install' required
- root privileges, verifies that the installation completed
- correctly.
-
- 6. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
- 7. Often, you can also type `make uninstall' to remove the installed
- files again. In practice, not all packages have tested that
- uninstallation works correctly, even though it is required by the
- GNU Coding Standards.
-
- 8. Some packages, particularly those that use Automake, provide `make
- distcheck', which can by used by developers to test that all other
- targets like `make install' and `make uninstall' work correctly.
- This target is generally not run by end users.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. Run `./configure --help'
-for details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you can use GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'. This
-is known as a "VPATH" build.
-
- With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory. After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
- On MacOS X 10.5 and later systems, you can create libraries and
-executables that work on multiple system types--known as "fat" or
-"universal" binaries--by specifying multiple `-arch' options to the
-compiler but only a single `-arch' option to the preprocessor. Like
-this:
-
- ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
- CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
- CPP="gcc -E" CXXCPP="g++ -E"
-
- This is not guaranteed to produce working output in all cases, you
-may have to build one architecture at a time and combine the results
-using the `lipo' tool if you have problems.
-
-Installation Names
-==================
-
- By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc. You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX', where PREFIX must be an
-absolute file name.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them. In general, the
-default for these options is expressed in terms of `${prefix}', so that
-specifying just `--prefix' will affect all of the other directory
-specifications that were not explicitly provided.
-
- The most portable way to affect installation locations is to pass the
-correct locations to `configure'; however, many packages provide one or
-both of the following shortcuts of passing variable assignments to the
-`make install' command line to change installation locations without
-having to reconfigure or recompile.
-
- The first method involves providing an override variable for each
-affected directory. For example, `make install
-prefix=/alternate/directory' will choose an alternate location for all
-directory configuration variables that were expressed in terms of
-`${prefix}'. Any directories that were specified during `configure',
-but not in terms of `${prefix}', must each be overridden at install
-time for the entire installation to be relocated. The approach of
-makefile variable overrides for each directory variable is required by
-the GNU Coding Standards, and ideally causes no recompilation.
-However, some platforms have known limitations with the semantics of
-shared libraries that end up requiring recompilation when using this
-method, particularly noticeable in packages that use GNU Libtool.
-
- The second method involves providing the `DESTDIR' variable. For
-example, `make install DESTDIR=/alternate/directory' will prepend
-`/alternate/directory' before all installation names. The approach of
-`DESTDIR' overrides is not required by the GNU Coding Standards, and
-does not work on platforms that have drive letters. On the other hand,
-it does better at avoiding recompilation issues, and works well even
-when some directory options were not specified in terms of `${prefix}'
-at `configure' time.
-
-Optional Features
-=================
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
- Some packages offer the ability to configure how verbose the
-execution of `make' will be. For these packages, running `./configure
---enable-silent-rules' sets the default to minimal output, which can be
-overridden with `make V=1'; while running `./configure
---disable-silent-rules' sets the default to verbose, which can be
-overridden with `make V=0'.
-
-Particular systems
-==================
-
- On HP-UX, the default C compiler is not ANSI C compatible. If GNU
-CC is not installed, it is recommended to use the following options in
-order to use an ANSI C compiler:
-
- ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
-
-and if that doesn't work, install pre-built binaries of GCC for HP-UX.
-
- HP-UX `make' updates targets which have the same time stamps as
-their prerequisites, which makes it generally unusable when shipped
-generated files such as `configure' are involved. Use GNU `make'
-instead.
-
- On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
-parse its `<wchar.h>' header file. The option `-nodtk' can be used as
-a workaround. If GNU CC is not installed, it is therefore recommended
-to try
-
- ./configure CC="cc"
-
-and if that doesn't work, try
-
- ./configure CC="cc -nodtk"
-
- On Solaris, don't put `/usr/ucb' early in your `PATH'. This
-directory contains several dysfunctional programs; working variants of
-these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
-in your `PATH', put it _after_ `/usr/bin'.
-
- On Haiku, software installed for all users goes in `/boot/common',
-not `/usr/local'. It is recommended to use the following options:
-
- ./configure --prefix=/boot/common
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on. Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS
- KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
- Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug. Until the bug is fixed you can use this workaround:
-
- CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
- Print a summary of all of the options to `configure', and exit.
-
-`--help=short'
-`--help=recursive'
- Print a summary of the options unique to this package's
- `configure', and exit. The `short' variant lists options used
- only in the top level, while the `recursive' variant lists options
- also present in any nested packages.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`--prefix=DIR'
- Use DIR as the installation prefix. *note Installation Names::
- for more details, including other options available for fine-tuning
- the installation locations.
-
-`--no-create'
-`-n'
- Run the configure checks, but stop before creating any output
- files.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
-
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/.gitmodules
^
|
@@ -1,3 +1,3 @@
[submodule "libhybris"]
path = libhybris
- url = https://github.com/elros34/libhybris-1
+ url = https://github.com/libhybris/libhybris
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/compat/camera/Android.mk
^
|
@@ -1,6 +1,12 @@
LOCAL_PATH:= $(call my-dir)
-HYBRIS_MEDIA_32_BIT_ONLY := $(shell cat frameworks/av/media/libmediaplayerservice/Android.mk |grep LOCAL_32_BIT_ONLY |grep -o "true\|false")
+ifneq (,$(wildcard frameworks/av/media/mediaserver/Android.mk))
+HYBRIS_MEDIA_32_BIT_ONLY := $(shell cat frameworks/av/media/mediaserver/Android.mk | grep LOCAL_32_BIT_ONLY | grep -o "true\|false")
+else
+ifneq (,$(wildcard frameworks/av/media/mediaserver/Android.bp))
+HYBRIS_MEDIA_32_BIT_ONLY := $(shell cat frameworks/av/media/mediaserver/Android.bp | grep compile_multilib | grep -wo "32" | sed "s/32/true/")
+endif
+endif
ifeq ($(HYBRIS_MEDIA_32_BIT_ONLY),true)
HYBRIS_MEDIA_MULTILIB := 32
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/compat/hwc2/Android.mk
^
|
@@ -12,10 +12,10 @@
LOCAL_C_INCLUDES := ../hybris/include
-ifeq ($(strip $(ANDROID_VERSION_MAJOR)),9)
+ifeq ($(shell test $(ANDROID_VERSION_MAJOR) -ge 9 && echo true),true)
LOCAL_C_INCLUDES += \
hardware/interfaces/graphics/composer/2.1/utils/command-buffer/include
-LOCAL_HEADER_LIBRARIES : \
+LOCAL_HEADER_LIBRARIES := \
android.hardware.graphics.composer@2.1-command-buffer
else
LOCAL_STATIC_LIBRARIES := \
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/compat/media/Android.mk
^
|
@@ -1,6 +1,12 @@
LOCAL_PATH:= $(call my-dir)
-HYBRIS_MEDIA_32_BIT_ONLY := $(shell cat frameworks/av/media/libmediaplayerservice/Android.mk |grep LOCAL_32_BIT_ONLY |grep -o "true\|false")
+ifneq (,$(wildcard frameworks/av/media/mediaserver/Android.mk))
+HYBRIS_MEDIA_32_BIT_ONLY := $(shell cat frameworks/av/media/mediaserver/Android.mk | grep LOCAL_32_BIT_ONLY | grep -o "true\|false")
+else
+ifneq (,$(wildcard frameworks/av/media/mediaserver/Android.bp))
+HYBRIS_MEDIA_32_BIT_ONLY := $(shell cat frameworks/av/media/mediaserver/Android.bp | grep compile_multilib | grep -wo "32" | sed "s/32/true/")
+endif
+endif
ifeq ($(HYBRIS_MEDIA_32_BIT_ONLY),true)
HYBRIS_MEDIA_MULTILIB := 32
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/Makefile.am
^
|
@@ -4,8 +4,10 @@
SUBDIRS =
if !WANT_ARCH_ARM64
+if !WANT_ARCH_X86_64
SUBDIRS += jb
endif
+endif
if HAS_ANDROID_6_0_0
SUBDIRS += mm
@@ -19,6 +21,10 @@
SUBDIRS += o
endif
+if HAS_ANDROID_10_0_0
+SUBDIRS += q
+endif
+
libhybris_common_la_SOURCES = \
hooks.c \
hooks_shm.c \
@@ -26,6 +32,7 @@
strlcat.c \
logging.c \
sysconf.c \
+ dso_handle_counters.cpp \
legacy_properties/properties.c \
legacy_properties/cache.c
@@ -52,14 +59,6 @@
libhybris_common_la_CPPFLAGS += -DWANT_ADRENO_QUIRKS
endif
-if WANT_ARM_TRACING
-# thumb mode not supported
-libhybris_common_la_CFLAGS += \
- -marm
-libhybris_common_la_CPPFLAGS += \
- -marm
-endif
-
if WANT_TRACE
libhybris_common_la_CPPFLAGS += -DDEBUG
endif
@@ -87,10 +86,18 @@
if HAS_ANDROID_8_0_0
libhybris_common_la_CPPFLAGS += -DWANT_LINKER_O
endif
+if HAS_ANDROID_10_0_0
+libhybris_common_la_CPPFLAGS += -DWANT_LINKER_Q
+endif
+
+libhybris_common_la_CXXFLAGS = \
+ -std=gnu++11
+
libhybris_common_la_LDFLAGS = \
-ldl \
-lrt \
-pthread \
-lc \
-lstdc++ \
+ -lpthread \
-version-info "$(LT_CURRENT)":"$(LT_REVISION)":"$(LT_AGE)"
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/dso_handle_counters.cpp
^
|
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 UBports Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unordered_map>
+#include <mutex>
+
+#include <dlfcn.h>
+#include <hybris/common/dlfcn.h>
+
+#include "logging.h"
+#define LOGD(message, ...) HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__)
+
+#include "dso_handle_counters.h"
+
+/*
+ * This file implements a reference-counting system for dso_handle symbols
+ * having outstanding thread-local variables. This is inspired by an
+ * implementation in Android's linker, but instead of using internal Linker
+ * mechanism, this file uses public linker functions to find the library and
+ * dlload() it to increment reference count.
+ *
+ * This file is implemented in C++ so that I can use C++'s unordered_map.
+ *
+ * See https://github.com/aosp-mirror/platform_bionic/commit/55547db4345ee692b9cfe727c97dd860ed8263f8
+ */
+
+struct DsoHandleInfo {
+ size_t counter;
+ void *dl_handle;
+};
+
+static std::unordered_map<void*, struct DsoHandleInfo *> g_dso_handle_counters;
+static std::mutex g_dso_handle_counters_mutex;
+
+void __hybris_add_thread_local_dtor(void* dso_handle)
+{
+ if (dso_handle == nullptr) {
+ return;
+ }
+
+ std::lock_guard<std::mutex> l(g_dso_handle_counters_mutex);
+
+ auto it = g_dso_handle_counters.find(dso_handle);
+ if (it != g_dso_handle_counters.end()) {
+ ++it->second->counter;
+ } else {
+ Dl_info dso_symbol_info;
+
+ if (hybris_dladdr(dso_handle, &dso_symbol_info)) {
+ struct DsoHandleInfo *info = new struct DsoHandleInfo;
+ info->counter = 1U;
+ info->dl_handle = hybris_dlopen(dso_symbol_info.dli_fname, /* flags */ 0);
+
+ g_dso_handle_counters[dso_handle] = info;
+ } else {
+ LOGD(
+ "__hybris_add_thread_local_dtor: Couldn't find a library by dso_handle=%p",
+ dso_handle);
+ // Nothing we can do.
+ }
+ }
+}
+
+void __hybris_remove_thread_local_dtor(void* dso_handle)
+{
+ if (dso_handle == nullptr) {
+ return;
+ }
+
+ // Do dlclose() outside the lock to avoid deadlock.
+ struct DsoHandleInfo *info = nullptr;
+
+ {
+ std::lock_guard<std::mutex> l(g_dso_handle_counters_mutex);
+
+ auto it = g_dso_handle_counters.find(dso_handle);
+
+ if (it == g_dso_handle_counters.end()) {
+ LOGD(
+ "__hybris_remove_thread_local_dtor: Couldn't find a library by dso_handle=%p",
+ dso_handle);
+ return;
+ }
+
+ if (--it->second->counter == 0) {
+ info = it->second;
+ g_dso_handle_counters.erase(it);
+ }
+ }
+
+ if (info) {
+ hybris_dlclose(info->dl_handle);
+ delete info;
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/dso_handle_counters.h
^
|
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 UBports Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _HYBRIS_DSO_HANDLE_COUNTERS_H_
+#define _HYBRIS_DSO_HANDLE_COUNTERS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __hybris_add_thread_local_dtor(void* dso_handle);
+void __hybris_remove_thread_local_dtor(void* dso_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HYBRIS_DSO_HANDLE_COUNTERS_H_
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/hooks.c
^
|
@@ -85,6 +85,8 @@
// this is also used in bionic:
#define bool int
+#include "dso_handle_counters.h"
+
#ifdef WANT_ARM_TRACING
#include "wrappers.h"
#endif
@@ -123,6 +125,10 @@
void (*_android_dlwarning)(void* obj, void (*f)(void*, const char*)) = NULL;
void *(*_android_get_exported_namespace)(const char* name) = NULL;
+#if WANT_LINKER_Q
+void * (*_android_shared_globals)() = NULL;
+#endif
+
/* TODO:
* - Check if the int arguments at attr_set/get match the ones at Android
* - Check how to deal with memory leaks (specially with static initializers)
@@ -1937,7 +1943,7 @@
*namelist = result;
}
- return res;
+ return nItems;
}
static int _hybris_hook_scandir(const char *dir,
@@ -2163,6 +2169,8 @@
extern int __cxa_atexit(void (*)(void*), void*, void*);
extern void __cxa_finalize(void * d);
+extern int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
+ void *dso_symbol);
struct open_redirect {
const char *from;
@@ -2239,6 +2247,46 @@
return tls_hooks;
}
+struct __wrapped_atexit {
+ void (*dtor)(void *);
+ void *obj;
+ void *dso_handle;
+};
+
+static void __dtor_wrapper(void *obj) {
+ struct __wrapped_atexit *wrapped = obj;
+ /* Call the wrapped dtor. */
+ wrapped->dtor(wrapped->obj);
+ /* Reduce dso_handle's ref count. */
+ __hybris_remove_thread_local_dtor(wrapped->dso_handle);
+ /* Free the wrapper. */
+ free(wrapped);
+}
+
+extern const void * const __dso_handle;
+
+static int _hybris_hook___cxa_thread_atexit(void (*dtor)(void *), void *obj,
+ void *dso_symbol)
+{
+ struct __wrapped_atexit *wrapped = malloc(sizeof(struct __wrapped_atexit));
+ wrapped->dtor = dtor;
+ wrapped->obj = obj;
+ wrapped->dso_handle = dso_symbol;
+
+ /* Call Glibc's implementation. Pass our symbol to prevent ourself from
+ * being unloaded. */
+ int ret;
+ if ((ret = __cxa_thread_atexit(__dtor_wrapper, wrapped, &__dso_handle)) != 0) {
+ free(wrapped);
+ return ret;
+ }
+
+ /* Increase refcount of this dso_symbol. */
+ __hybris_add_thread_local_dtor(dso_symbol);
+
+ return ret;
+}
+
int _hybris_hook_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
@@ -2645,7 +2693,14 @@
return _android_create_namespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent);
}
+#if WANT_LINKER_Q
+void* _hybris_hook___loader_shared_globals()
+{
+ TRACE("");
+ return _android_shared_globals();
+}
+#endif
bool _hybris_hook_android_init_anonymous_namespace(const char* shared_libs_sonames,
const char* library_search_path)
{
@@ -2930,10 +2985,14 @@
HOOK_INDIRECT(android_init_anonymous_namespace),
HOOK_INDIRECT(android_dlwarning),
HOOK_INDIRECT(android_get_exported_namespace),
+#if WANT_LINKER_Q
+ HOOK_INDIRECT(__loader_shared_globals),
+#endif
/* dirent.h */
HOOK_DIRECT_NO_DEBUG(opendir),
HOOK_DIRECT_NO_DEBUG(fdopendir),
HOOK_DIRECT_NO_DEBUG(closedir),
+ HOOK_DIRECT_NO_DEBUG(__fsetlocking),
HOOK_INDIRECT(readdir),
HOOK_INDIRECT(readdir_r),
HOOK_DIRECT_NO_DEBUG(rewinddir),
@@ -2970,8 +3029,10 @@
HOOK_DIRECT_NO_DEBUG(access),
/* grp.h */
HOOK_DIRECT_NO_DEBUG(getgrgid),
+ /* C++ ABI */
HOOK_DIRECT_NO_DEBUG(__cxa_atexit),
HOOK_DIRECT_NO_DEBUG(__cxa_finalize),
+ HOOK_INDIRECT(__cxa_thread_atexit),
/* sys/prctl.h */
HOOK_INDIRECT(prctl),
/* stdio_ext.h */
@@ -3012,6 +3073,7 @@
HOOK_DIRECT_NO_DEBUG(ptsname),
HOOK_TO(__hybris_set_errno_internal, _hybris_hook___set_errno),
HOOK_DIRECT_NO_DEBUG(getservbyname),
+ HOOK_DIRECT_NO_DEBUG(close), /* avoid calling fdsan functions */
/* libgen.h */
HOOK_INDIRECT(basename),
HOOK_INDIRECT(dirname),
@@ -3105,8 +3167,12 @@
#define LINKER_NAME_MM "mm"
#define LINKER_NAME_N "n"
#define LINKER_NAME_O "o"
+#define LINKER_NAME_Q "q"
-#if defined(WANT_LINKER_O)
+#if defined(WANT_LINKER_Q)
+#define LINKER_VERSION_DEFAULT 29
+#define LINKER_NAME_DEFAULT LINKER_NAME_Q
+#elif defined(WANT_LINKER_O)
#define LINKER_VERSION_DEFAULT 27
#define LINKER_NAME_DEFAULT LINKER_NAME_O
#elif defined(WANT_LINKER_N)
@@ -3210,7 +3276,7 @@
key.name = sym;
sdk_version = get_android_sdk_version();
-#if defined(WANT_LINKER_MM) || defined(WANT_LINKER_N) || defined(WANT_LINKER_O)
+#if defined(WANT_LINKER_MM) || defined(WANT_LINKER_N) || defined(WANT_LINKER_O) || defined(WANT_LINKER_Q)
if (sdk_version > 21)
found = bsearch(&key, hooks_mm, HOOKS_SIZE(hooks_mm), sizeof(hooks_mm[0]), hook_cmp);
#endif
@@ -3287,6 +3353,10 @@
/* See https://source.android.com/source/build-numbers.html for
* an overview over available SDK version numbers and which
* Android version they relate to. */
+#if defined(WANT_LINKER_Q)
+ if (sdk_version <= 29)
+ name = LINKER_NAME_Q;
+#endif
#if defined(WANT_LINKER_O)
if (sdk_version <= 27)
name = LINKER_NAME_O;
@@ -3340,7 +3410,9 @@
_android_init_anonymous_namespace = dlsym(linker_handle, "android_init_anonymous_namespace");
_android_dlwarning = dlsym(linker_handle, "android_dlwarning");
_android_get_exported_namespace = dlsym(linker_handle, "android_get_exported_namespace");
-
+#if WANT_LINKER_Q
+ _android_shared_globals = dlsym(linker_handle, "android_shared_globals");
+#endif
/* Now its time to setup the linker itself */
#ifdef WANT_ARM_TRACING
_android_linker_init(sdk_version, __hybris_get_hooked_symbol, enable_linker_gdb_support, create_wrapper);
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/jb/dlfcn.c
^
|
@@ -23,6 +23,12 @@
#include "linker.h"
#include "linker_format.h"
+#ifdef WANT_ARM_TRACING
+#include "../wrappers.h"
+
+extern void *(*_create_wrapper)(const char *symbol, void *function, int wrapper_type);
+#endif
+
/* This file hijacks the symbols stubbed out in libdl.so. */
#define DL_SUCCESS 0
@@ -115,6 +121,15 @@
if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) {
unsigned ret = sym->st_value + found->base;
+#ifdef WANT_ARM_TRACING
+ switch(ELF32_ST_TYPE(sym->st_info))
+ {
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ case STT_ARM_TFUNC:
+ ret = (void*)(_create_wrapper((char*)symbol, (void*)ret, WRAPPER_DYNHOOK));
+ }
+#endif
pthread_mutex_unlock(&dl_lock);
return (void*)ret;
}
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/jb/linker.c
^
|
@@ -51,6 +51,10 @@
#include "linker_environ.h"
#include "linker_format.h"
+#ifdef WANT_ARM_TRACING
+#include "../wrappers.h"
+#endif
+
#define ALLOW_SYMBOLS_FROM_MAIN 1
#define SO_MAX 128
@@ -81,6 +85,10 @@
* having a hard limit (64)
*/
+#ifdef WANT_ARM_TRACING
+void *(*_create_wrapper)(const char *symbol, void *function, int wrapper_type);
+#endif
+
static void* (*_get_hooked_symbol)(const char *symbol, const char *requester);
static int link_image(soinfo *si, unsigned wr_offset);
@@ -1377,8 +1385,21 @@
if (sym_addr != 0) {
INFO("HYBRIS: '%s' hooked symbol %s to %x\n", si->name,
sym_name, sym_addr);
+#ifdef WANT_ARM_TRACING
+ s = _do_lookup(si, sym_name, &base);
+ if(s != NULL) {
+ switch(ELF32_ST_TYPE(s->st_info))
+ {
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ case STT_ARM_TFUNC:
+ sym_addr = (unsigned)_create_wrapper(sym_name, (void*)sym_addr, WRAPPER_HOOKED);
+ break;
+ }
+ }
+#endif
} else {
- s = _do_lookup(si, sym_name, &base);
+ s = _do_lookup(si, sym_name, &base);
}
if(sym_addr == 0) {
if(s == NULL) {
@@ -1447,7 +1468,22 @@
return -1;
}
#endif
+#ifdef WANT_ARM_TRACING
+ switch(ELF32_ST_TYPE(s->st_info))
+ {
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ case STT_ARM_TFUNC:
+ sym_addr = (unsigned)_create_wrapper(sym_name,
+ (unsigned)(s->st_value + base), WRAPPER_UNHOOKED);
+ break;
+ default:
+ sym_addr = (unsigned)(s->st_value + base);
+ break;
+ }
+#else
sym_addr = (unsigned)(s->st_value + base);
+#endif
}
}
COUNT_RELOC(RELOC_SYMBOL);
@@ -2388,5 +2424,8 @@
#endif
(void) sdk_version;
_get_hooked_symbol = get_hooked_symbol;
+#ifdef WANT_ARM_TRACING
+ _create_wrapper = create_wrapper;
+#endif
_linker_enable_gdb_support = enable_linker_gdb_support;
}
|
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/MODULE_LICENSE_BSD
^
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/Makefile.am
^
|
@@ -0,0 +1,71 @@
+bionic = $(top_srcdir)/common/q/bionic
+bionic_libc = $(bionic)/libc
+
+modlibexecdir = $(libdir)/libhybris/linker
+modlibexec_LTLIBRARIES = q.la
+
+ARCH_FLAGS =
+
+AM_CFLAGS = \
+ -std=gnu99
+
+AM_CPPFLAGS = \
+ -fno-stack-protector \
+ -Wstrict-overflow=5
+
+AM_CXXFLAGS = \
+ -std=gnu++11 \
+ -Wold-style-cast
+
+q_la_SOURCES = \
+ hybris_compat.cpp \
+ dlfcn.cpp \
+ linker_allocator.cpp \
+ linker_block_allocator.cpp \
+ linker.cpp \
+ linker_cfi.cpp \
+ linker_config.cpp \
+ linker_dlwarning.cpp \
+ linker_gdb_support.cpp \
+ linker_globals.cpp \
+ linker_logger.cpp \
+ linker_main.cpp \
+ linker_mapped_file_fragment.cpp \
+ linker_memory.cpp \
+ linker_namespaces.cpp \
+ linker_phdr.cpp \
+ linker_sdk_versions.cpp \
+ linker_soinfo.cpp \
+ linker_tls.cpp \
+ linker_utils.cpp \
+ rt.cpp \
+ ../strlcpy.c \
+ ../strlcat.c
+q_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/common \
+ -I$(bionic_libc)/ \
+ -I$(bionic_libc)/include \
+ -DDEFAULT_HYBRIS_LD_LIBRARY_PATH="\"@DEFAULT_HYBRIS_LD_LIBRARY_PATH@\"" \
+ -D_USING_LIBCXX \
+ $(ARCH_FLAGS) \
+ $(ANDROID_HEADERS_CFLAGS)
+q_la_LDFLAGS = \
+ -lsupc++ \
+ -module \
+ -avoid-version
+
+if WANT_DEBUG
+q_la_CPPFLAGS += \
+ -DTRACE_DEBUG=1
+else
+q_la_CPPFLAGS += \
+ -DTRACE_DEBUG=1
+endif
+
+if WANT_ARM_TRACING
+q_la_CPPFLAGS += \
+ -DWANT_ARM_TRACING
+endif
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/async_safe/CHECK.h
^
|
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#include <async_safe/log.h>
+
+__BEGIN_DECLS
+
+// TODO: replace this with something more like <android-base/logging.h>'s family of macros.
+
+#define CHECK(predicate) \
+ do { \
+ if (!(predicate)) { \
+ async_safe_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ } while(0)
+
+__END_DECLS
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/async_safe/log.h
^
|
@@ -0,0 +1,27 @@
+#ifndef thatasyncsafeheaderthingy_replacement__
+#define thatasyncsafeheaderthingy_replacement__
+
+#include <stdio.h>
+enum {
+ ANDROID_LOG_UNKNOWN = 0,
+ ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
+
+ ANDROID_LOG_VERBOSE,
+ ANDROID_LOG_DEBUG,
+ ANDROID_LOG_INFO,
+ ANDROID_LOG_WARN,
+ ANDROID_LOG_ERROR,
+ ANDROID_LOG_FATAL,
+
+ ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
+};
+
+#define async_safe_fatal(...) { fprintf(stderr, __VA_ARGS__); abort(); }
+
+#define async_safe_format_fd(fd, ...) dprintf(fd, __VA_ARGS__)
+
+// Don't really care about verbose/debug logs for now
+#define async_safe_format_log_va_list(loglevel, category, format, ...) { if (loglevel > ANDROID_LOG_DEFAULT) { vfprintf(stdout, format, __VA_ARGS__); /*vfprintf(stderr, "%s", "\n");*/} }
+
+#endif
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/bionic/libc_init_common.h
^
|
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs-android.h>
+
+typedef struct {
+ void (**preinit_array)(void);
+ void (**init_array)(void);
+ void (**fini_array)(void);
+} structors_array_t;
+
+__BEGIN_DECLS
+
+extern int main(int argc, char** argv, char** env);
+
+void __libc_init(void* raw_args,
+ void (*onexit)(void),
+ int (*slingshot)(int, char**, char**),
+ structors_array_t const* const structors);
+__LIBC_HIDDEN__ void __libc_fini(void* finit_array);
+
+__END_DECLS
+
+#if defined(__cplusplus)
+
+__LIBC_HIDDEN__ void __libc_init_globals();
+
+__LIBC_HIDDEN__ void __libc_init_common();
+
+__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/bionic/pthread_internal.h
^
|
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <pthread.h>
+#include <stdatomic.h>
+#define __has_feature(x) 0
+#if __has_feature(hwaddress_sanitizer)
+#include <sanitizer/hwasan_interface.h>
+#else
+#define __hwasan_thread_enter()
+#define __hwasan_thread_exit()
+#endif
+
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_lock.h"
+#include "private/bionic_tls.h"
+
+// Has the thread been detached by a pthread_join or pthread_detach call?
+#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
+
+// Has the thread been joined by another thread?
+#define PTHREAD_ATTR_FLAG_JOINED 0x00000002
+
+// Used for pthread_attr_setinheritsched. We need two flags for this apparent
+// boolean because our historical behavior matches neither of the POSIX choices.
+#define PTHREAD_ATTR_FLAG_INHERIT 0x00000004
+#define PTHREAD_ATTR_FLAG_EXPLICIT 0x00000008
+
+enum ThreadJoinState {
+ THREAD_NOT_JOINED,
+ THREAD_EXITED_NOT_JOINED,
+ THREAD_JOINED,
+ THREAD_DETACHED
+};
+
+class thread_local_dtor;
+
+class pthread_internal_t {
+ public:
+ class pthread_internal_t* next;
+ class pthread_internal_t* prev;
+
+ pid_t tid;
+
+ private:
+ pid_t cached_pid_;
+
+ public:
+ pid_t invalidate_cached_pid() {
+ pid_t old_value;
+ get_cached_pid(&old_value);
+ set_cached_pid(0);
+ return old_value;
+ }
+
+ void set_cached_pid(pid_t value) {
+ cached_pid_ = value;
+ }
+
+ bool get_cached_pid(pid_t* cached_pid) {
+ *cached_pid = cached_pid_;
+ return (*cached_pid != 0);
+ }
+
+ pthread_attr_t attr;
+
+ _Atomic(ThreadJoinState) join_state;
+
+ //__pthread_cleanup_t* cleanup_stack;
+
+ void* (*start_routine)(void*);
+ void* start_routine_arg;
+ void* return_value;
+
+ void* alternate_signal_stack;
+
+ // The start address of the shadow call stack's guard region (arm64 only).
+ // This address is only used to deallocate the shadow call stack on thread
+ // exit; the address of the stack itself is stored only in the x18 register.
+ // Because the protection offered by SCS relies on the secrecy of the stack
+ // address, storing the address here weakens the protection, but only
+ // slightly, because it is relatively easy for an attacker to discover the
+ // address of the guard region anyway (e.g. it can be discovered by reference
+ // to other allocations), but not the stack itself, which is <0.1% of the size
+ // of the guard region.
+ //
+ // There are at least two other options for discovering the start address of
+ // the guard region on thread exit, but they are not as simple as storing in
+ // TLS.
+ // 1) Derive it from the value of the x18 register. This is only possible in
+ // processes that do not contain legacy code that might clobber x18,
+ // therefore each process must declare early during process startup whether
+ // it might load legacy code.
+ // 2) Mark the guard region as such using prctl(PR_SET_VMA_ANON_NAME) and
+ // discover its address by reading /proc/self/maps. One issue with this is
+ // that reading /proc/self/maps can race with allocations, so we may need
+ // code to handle retries.
+ void* shadow_call_stack_guard_region;
+
+ Lock startup_handshake_lock;
+
+ void* mmap_base;
+ size_t mmap_size;
+
+ thread_local_dtor* thread_local_dtors;
+
+ /*
+ * The dynamic linker implements dlerror(3), which makes it hard for us to implement this
+ * per-thread buffer by simply using malloc(3) and free(3).
+ */
+ char* current_dlerror;
+#define __BIONIC_DLERROR_BUFFER_SIZE 512
+ char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
+
+ struct bionic_tls* bionic_tls;
+
+ int errno_value;
+};
+
+struct ThreadMapping {
+ char* mmap_base;
+ size_t mmap_size;
+
+ char* static_tls;
+ char* stack_base;
+ char* stack_top;
+};
+
+__LIBC_HIDDEN__ void __init_tcb(bionic_tcb* tcb, pthread_internal_t* thread);
+__LIBC_HIDDEN__ void __init_tcb_stack_guard(bionic_tcb* tcb);
+__LIBC_HIDDEN__ void __init_tcb_dtv(bionic_tcb* tcb);
+__LIBC_HIDDEN__ void __init_bionic_tls_ptrs(bionic_tcb* tcb, bionic_tls* tls);
+__LIBC_HIDDEN__ bionic_tls* __allocate_temp_bionic_tls();
+__LIBC_HIDDEN__ void __free_temp_bionic_tls(bionic_tls* tls);
+__LIBC_HIDDEN__ void __init_additional_stacks(pthread_internal_t*);
+__LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
+__LIBC_HIDDEN__ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size);
+
+__LIBC_HIDDEN__ pthread_t __pthread_internal_add(pthread_internal_t* thread);
+__LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id, const char* caller);
+__LIBC_HIDDEN__ pid_t __pthread_internal_gettid(pthread_t pthread_id, const char* caller);
+__LIBC_HIDDEN__ void __pthread_internal_remove(pthread_internal_t* thread);
+__LIBC_HIDDEN__ void __pthread_internal_remove_and_free(pthread_internal_t* thread);
+
+static inline bionic_tcb* __get_bionic_tcb() {
+ return reinterpret_cast<bionic_tcb*>(&__get_tls()[MIN_TLS_SLOT]);
+}
+
+// Make __get_thread() inlined for performance reason. See http://b/19825434.
+static inline pthread_internal_t* __get_thread() {
+ return static_cast<pthread_internal_t*>(__get_tls()[TLS_SLOT_THREAD_ID]);
+}
+
+static inline bionic_tls& __get_bionic_tls() {
+ return *static_cast<bionic_tls*>(__get_tls()[TLS_SLOT_BIONIC_TLS]);
+}
+
+static inline TlsDtv* __get_tcb_dtv(bionic_tcb* tcb) {
+ uintptr_t dtv_slot = reinterpret_cast<uintptr_t>(tcb->tls_slot(TLS_SLOT_DTV));
+ return reinterpret_cast<TlsDtv*>(dtv_slot - offsetof(TlsDtv, generation));
+}
+
+static inline void __set_tcb_dtv(bionic_tcb* tcb, TlsDtv* val) {
+ tcb->tls_slot(TLS_SLOT_DTV) = &val->generation;
+}
+
+extern "C" __LIBC_HIDDEN__ int __set_tls(void* ptr);
+
+__LIBC_HIDDEN__ void pthread_key_clean_all(void);
+
+// Address space is precious on LP32, so use the minimum unit: one page.
+// On LP64, we could use more but there's no obvious advantage to doing
+// so, and the various media processes use RLIMIT_AS as a way to limit
+// the amount of allocation they'll do.
+#define PTHREAD_GUARD_SIZE PAGE_SIZE
+
+// SIGSTKSZ (8KiB) is not big enough.
+// An snprintf to a stack buffer of size PATH_MAX consumes ~7KiB of stack.
+// On 64-bit, logging uses more than 8KiB by itself, ucontext is comically
+// large on aarch64, and we have effectively infinite address space, so double
+// the signal stack size.
+#if defined(__LP64__)
+#define SIGNAL_STACK_SIZE_WITHOUT_GUARD (32 * 1024)
+#else
+#define SIGNAL_STACK_SIZE_WITHOUT_GUARD (16 * 1024)
+#endif
+
+// Traditionally we gave threads a 1MiB stack. When we started
+// allocating per-thread alternate signal stacks to ease debugging of
+// stack overflows, we subtracted the same amount we were using there
+// from the default thread stack size. This should keep memory usage
+// roughly constant.
+#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
+
+// Leave room for a guard page in the internally created signal stacks.
+#define SIGNAL_STACK_SIZE (SIGNAL_STACK_SIZE_WITHOUT_GUARD + PTHREAD_GUARD_SIZE)
+
+// Needed by fork.
+__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
+__LIBC_HIDDEN__ extern void __bionic_atfork_run_child();
+__LIBC_HIDDEN__ extern void __bionic_atfork_run_parent();
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/chrono_utils.h
^
|
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <chrono>
+#include <sstream>
+
+#if __cplusplus > 201103L && !defined(__WIN32) // C++14
+using namespace std::chrono_literals;
+#endif
+
+namespace android {
+namespace base {
+
+// A std::chrono clock based on CLOCK_BOOTTIME.
+class boot_clock {
+ public:
+ typedef std::chrono::nanoseconds duration;
+ typedef std::chrono::time_point<boot_clock, duration> time_point;
+
+ static time_point now();
+};
+
+class Timer {
+ public:
+ Timer() : start_(boot_clock::now()) {}
+
+ std::chrono::milliseconds duration() const {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now() - start_);
+ }
+
+ private:
+ boot_clock::time_point start_;
+};
+
+std::ostream& operator<<(std::ostream& os, const Timer& t);
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/cmsg.h
^
|
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <type_traits>
+#include <vector>
+
+#include <android-base/collections.h>
+#include <android-base/macros.h>
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace base {
+
+#if !defined(_WIN32)
+
+// Helpers for sending and receiving file descriptors across Unix domain sockets.
+//
+// The cmsg(3) API is very hard to get right, with multiple landmines that can
+// lead to death. Almost all of the uses of cmsg in Android make at least one of
+// the following mistakes:
+//
+// - not aligning the cmsg buffer
+// - leaking fds if more fds are received than expected
+// - blindly dereferencing CMSG_DATA without checking the header
+// - using CMSG_SPACE instead of CMSG_LEN for .cmsg_len
+// - using CMSG_LEN instead of CMSG_SPACE for .msg_controllen
+// - using a length specified in number of fds instead of bytes
+//
+// These functions wrap the hard-to-use cmsg API with an easier to use abstraction.
+
+// Send file descriptors across a Unix domain socket.
+//
+// Note that the write can return short if the socket type is SOCK_STREAM. When
+// this happens, file descriptors are still sent to the other end, but with
+// truncated data. For this reason, using SOCK_SEQPACKET or SOCK_DGRAM is recommended.
+ssize_t SendFileDescriptorVector(int sock, const void* data, size_t len,
+ const std::vector<int>& fds);
+
+// Receive file descriptors from a Unix domain socket.
+//
+// If more FDs (or bytes, for datagram sockets) are received than expected,
+// -1 is returned with errno set to EMSGSIZE, and all received FDs are thrown away.
+ssize_t ReceiveFileDescriptorVector(int sock, void* data, size_t len, size_t max_fds,
+ std::vector<android::base::unique_fd>* fds);
+
+// Helper for SendFileDescriptorVector that constructs a std::vector for you, e.g.:
+// SendFileDescriptors(sock, "foo", 3, std::move(fd1), std::move(fd2))
+template <typename... Args>
+ssize_t SendFileDescriptors(int sock, const void* data, size_t len, Args&&... sent_fds) {
+ // Do not allow implicit conversion to int: people might try to do something along the lines of:
+ // SendFileDescriptors(..., std::move(a_unique_fd))
+ // and be surprised when the unique_fd isn't closed afterwards.
+ AssertType<int>(std::forward<Args>(sent_fds)...);
+ std::vector<int> fds;
+ Append(fds, std::forward<Args>(sent_fds)...);
+ return SendFileDescriptorVector(sock, data, len, fds);
+}
+
+// Helper for ReceiveFileDescriptorVector that receives an exact number of file descriptors.
+// If more file descriptors are received than requested, -1 is returned with errno set to EMSGSIZE.
+// If fewer file descriptors are received than requested, -1 is returned with errno set to ENOMSG.
+// In both cases, all arguments are cleared and any received FDs are thrown away.
+template <typename... Args>
+ssize_t ReceiveFileDescriptors(int sock, void* data, size_t len, Args&&... received_fds) {
+ std::vector<unique_fd*> fds;
+ Append(fds, std::forward<Args>(received_fds)...);
+
+ std::vector<unique_fd> result;
+ ssize_t rc = ReceiveFileDescriptorVector(sock, data, len, fds.size(), &result);
+ if (rc == -1 || result.size() != fds.size()) {
+ int err = rc == -1 ? errno : ENOMSG;
+ for (unique_fd* fd : fds) {
+ fd->reset();
+ }
+ errno = err;
+ return -1;
+ }
+
+ for (size_t i = 0; i < fds.size(); ++i) {
+ *fds[i] = std::move(result[i]);
+ }
+ return rc;
+}
+
+#endif
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/collections.h
^
|
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utility>
+
+namespace android {
+namespace base {
+
+// Helpers for converting a variadic template parameter pack to a homogeneous collection.
+// Parameters must be implictly convertible to the contained type (including via move/copy ctors).
+//
+// Use as follows:
+//
+// template <typename... Args>
+// std::vector<int> CreateVector(Args&&... args) {
+// std::vector<int> result;
+// Append(result, std::forward<Args>(args)...);
+// return result;
+// }
+template <typename CollectionType, typename T>
+void Append(CollectionType& collection, T&& arg) {
+ collection.push_back(std::forward<T>(arg));
+}
+
+template <typename CollectionType, typename T, typename... Args>
+void Append(CollectionType& collection, T&& arg, Args&&... args) {
+ collection.push_back(std::forward<T>(arg));
+ return Append(collection, std::forward<Args>(args)...);
+}
+
+// Assert that all of the arguments in a variadic template parameter pack are of a given type
+// after std::decay.
+template <typename T, typename Arg, typename... Args>
+void AssertType(Arg&&) {
+ static_assert(std::is_same<T, typename std::decay<Arg>::type>::value);
+}
+
+template <typename T, typename Arg, typename... Args>
+void AssertType(Arg&&, Args&&... args) {
+ static_assert(std::is_same<T, typename std::decay<Arg>::type>::value);
+ AssertType<T>(std::forward<Args>(args)...);
+}
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/endian.h
^
|
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/* A cross-platform equivalent of bionic's <sys/endian.h>. */
+
+#if defined(__BIONIC__)
+
+#include <sys/endian.h>
+
+#elif defined(__GLIBC__)
+
+/* glibc's <endian.h> is like bionic's <sys/endian.h>. */
+#include <endian.h>
+
+/* glibc keeps htons and htonl in <netinet/in.h>. */
+#include <netinet/in.h>
+
+/* glibc doesn't have the 64-bit variants. */
+#define htonq(x) htobe64(x)
+#define ntohq(x) be64toh(x)
+
+/* glibc has different names to BSD for these. */
+#define betoh16(x) be16toh(x)
+#define betoh32(x) be32toh(x)
+#define betoh64(x) be64toh(x)
+
+#else
+
+/* Mac OS and Windows have nothing. */
+
+#define __LITTLE_ENDIAN 1234
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+
+#define __BIG_ENDIAN 4321
+#define BIG_ENDIAN __BIG_ENDIAN
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#define BYTE_ORDER __BYTE_ORDER
+
+#define htons(x) __builtin_bswap16(x)
+#define htonl(x) __builtin_bswap32(x)
+#define htonq(x) __builtin_bswap64(x)
+
+#define ntohs(x) __builtin_bswap16(x)
+#define ntohl(x) __builtin_bswap32(x)
+#define ntohq(x) __builtin_bswap64(x)
+
+#define htobe16(x) __builtin_bswap16(x)
+#define htobe32(x) __builtin_bswap32(x)
+#define htobe64(x) __builtin_bswap64(x)
+
+#define betoh16(x) __builtin_bswap16(x)
+#define betoh32(x) __builtin_bswap32(x)
+#define betoh64(x) __builtin_bswap64(x)
+
+#define htole16(x) (x)
+#define htole32(x) (x)
+#define htole64(x) (x)
+
+#define letoh16(x) (x)
+#define letoh32(x) (x)
+#define letoh64(x) (x)
+
+#define be16toh(x) __builtin_bswap16(x)
+#define be32toh(x) __builtin_bswap32(x)
+#define be64toh(x) __builtin_bswap64(x)
+
+#define le16toh(x) (x)
+#define le32toh(x) (x)
+#define le64toh(x) (x)
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/errors.h
^
|
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Portable error handling functions. This is only necessary for host-side
+// code that needs to be cross-platform; code that is only run on Unix should
+// just use errno and strerror() for simplicity.
+//
+// There is some complexity since Windows has (at least) three different error
+// numbers, not all of which share the same type:
+// * errno: for C runtime errors.
+// * GetLastError(): Windows non-socket errors.
+// * WSAGetLastError(): Windows socket errors.
+// errno can be passed to strerror() on all platforms, but the other two require
+// special handling to get the error string. Refer to Microsoft documentation
+// to determine which error code to check for each function.
+
+#pragma once
+
+#include <string>
+
+namespace android {
+namespace base {
+
+// Returns a string describing the given system error code. |error_code| must
+// be errno on Unix or GetLastError()/WSAGetLastError() on Windows. Passing
+// errno on Windows has undefined behavior.
+std::string SystemErrorCodeToString(int error_code);
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/file.h
^
|
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <string>
+
+#include <android-base/macros.h>
+#include "android-base/off64_t.h"
+
+#if !defined(_WIN32) && !defined(O_BINARY)
+/** Windows needs O_BINARY, but Unix never mangles line endings. */
+#define O_BINARY 0
+#endif
+
+#if defined(_WIN32) && !defined(O_CLOEXEC)
+/** Windows has O_CLOEXEC but calls it O_NOINHERIT for some reason. */
+#define O_CLOEXEC O_NOINHERIT
+#endif
+
+class TemporaryFile {
+ public:
+ TemporaryFile();
+ explicit TemporaryFile(const std::string& tmp_dir);
+ ~TemporaryFile();
+
+ // Release the ownership of fd, caller is reponsible for closing the
+ // fd or stream properly.
+ int release();
+ // Don't remove the temporary file in the destructor.
+ void DoNotRemove() { remove_file_ = false; }
+
+ int fd;
+ char path[1024];
+
+ private:
+ void init(const std::string& tmp_dir);
+
+ bool remove_file_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryFile);
+};
+
+class TemporaryDir {
+ public:
+ TemporaryDir();
+ ~TemporaryDir();
+ // Don't remove the temporary dir in the destructor.
+ void DoNotRemove() { remove_dir_and_contents_ = false; }
+
+ char path[1024];
+
+ private:
+ bool init(const std::string& tmp_dir);
+
+ bool remove_dir_and_contents_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
+};
+
+namespace android {
+namespace base {
+
+bool ReadFdToString(int fd, std::string* content);
+bool ReadFileToString(const std::string& path, std::string* content,
+ bool follow_symlinks = false);
+
+bool WriteStringToFile(const std::string& content, const std::string& path,
+ bool follow_symlinks = false);
+bool WriteStringToFd(const std::string& content, int fd);
+
+#if !defined(_WIN32)
+bool WriteStringToFile(const std::string& content, const std::string& path,
+ mode_t mode, uid_t owner, gid_t group,
+ bool follow_symlinks = false);
+#endif
+
+bool ReadFully(int fd, void* data, size_t byte_count);
+
+// Reads `byte_count` bytes from the file descriptor at the specified offset.
+// Returns false if there was an IO error or EOF was reached before reading `byte_count` bytes.
+//
+// NOTE: On Linux/Mac, this function wraps pread, which provides atomic read support without
+// modifying the read pointer of the file descriptor. On Windows, however, the read pointer does
+// get modified. This means that ReadFullyAtOffset can be used concurrently with other calls to the
+// same function, but concurrently seeking or reading incrementally can lead to unexpected
+// behavior.
+bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset);
+
+bool WriteFully(int fd, const void* data, size_t byte_count);
+
+bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr);
+
+#if !defined(_WIN32)
+bool Realpath(const std::string& path, std::string* result);
+bool Readlink(const std::string& path, std::string* result);
+#endif
+
+std::string GetExecutablePath();
+std::string GetExecutableDirectory();
+
+// Like the regular basename and dirname, but thread-safe on all
+// platforms and capable of correctly handling exotic Windows paths.
+std::string Basename(const std::string& path);
+std::string Dirname(const std::string& path);
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/logging.h
^
|
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+//
+// Google-style C++ logging.
+//
+
+// This header provides a C++ stream interface to logging.
+//
+// To log:
+//
+// LOG(INFO) << "Some text; " << some_value;
+//
+// Replace `INFO` with any severity from `enum LogSeverity`.
+//
+// To log the result of a failed function and include the string
+// representation of `errno` at the end:
+//
+// PLOG(ERROR) << "Write failed";
+//
+// The output will be something like `Write failed: I/O error`.
+// Remember this as 'P' as in perror(3).
+//
+// To output your own types, simply implement operator<< as normal.
+//
+// By default, output goes to logcat on Android and stderr on the host.
+// A process can use `SetLogger` to decide where all logging goes.
+// Implementations are provided for logcat, stderr, and dmesg.
+//
+// By default, the process' name is used as the log tag.
+// Code can choose a specific log tag by defining LOG_TAG
+// before including this header.
+
+// This header also provides assertions:
+//
+// CHECK(must_be_true);
+// CHECK_EQ(a, b) << z_is_interesting_too;
+
+// NOTE: For Windows, you must include logging.h after windows.h to allow the
+// following code to suppress the evil ERROR macro:
+#ifdef _WIN32
+// windows.h includes wingdi.h which defines an evil macro ERROR.
+#ifdef ERROR
+#undef ERROR
+#endif
+#endif
+
+#include <functional>
+#include <memory>
+#include <ostream>
+
+#include "android-base/macros.h"
+
+// Note: DO NOT USE DIRECTLY. Use LOG_TAG instead.
+#ifdef _LOG_TAG_INTERNAL
+#error "_LOG_TAG_INTERNAL must not be defined"
+#endif
+#ifdef LOG_TAG
+#define _LOG_TAG_INTERNAL LOG_TAG
+#else
+#define _LOG_TAG_INTERNAL nullptr
+#endif
+
+namespace android {
+namespace base {
+
+enum LogSeverity {
+ VERBOSE,
+ DEBUG,
+ INFO,
+ WARNING,
+ ERROR,
+ FATAL_WITHOUT_ABORT,
+ FATAL,
+};
+
+enum LogId {
+ DEFAULT,
+ MAIN,
+ SYSTEM,
+};
+
+using LogFunction = std::function<void(LogId, LogSeverity, const char*, const char*,
+ unsigned int, const char*)>;
+using AbortFunction = std::function<void(const char*)>;
+
+// Loggers for use with InitLogging/SetLogger.
+
+// Log to the kernel log (dmesg).
+void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+// Log to stderr in the full logcat format (with pid/tid/time/tag details).
+void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+// Log just the message to stdout/stderr (without pid/tid/time/tag details).
+// The choice of stdout versus stderr is based on the severity.
+// Errors are also prefixed by the program name (as with err(3)/error(3)).
+// Useful for replacing printf(3)/perror(3)/err(3)/error(3) in command-line tools.
+void StdioLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+
+void DefaultAborter(const char* abort_message);
+
+std::string GetDefaultTag();
+void SetDefaultTag(const std::string& tag);
+
+#ifdef __ANDROID__
+// We expose this even though it is the default because a user that wants to
+// override the default log buffer will have to construct this themselves.
+class LogdLogger {
+ public:
+ explicit LogdLogger(LogId default_log_id = android::base::MAIN);
+
+ void operator()(LogId, LogSeverity, const char* tag, const char* file,
+ unsigned int line, const char* message);
+
+ private:
+ LogId default_log_id_;
+};
+#endif
+
+// Configure logging based on ANDROID_LOG_TAGS environment variable.
+// We need to parse a string that looks like
+//
+// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
+//
+// The tag (or '*' for the global level) comes first, followed by a colon and a
+// letter indicating the minimum priority level we're expected to log. This can
+// be used to reveal or conceal logs with specific tags.
+#ifdef __ANDROID__
+#define INIT_LOGGING_DEFAULT_LOGGER LogdLogger()
+#else
+#define INIT_LOGGING_DEFAULT_LOGGER StderrLogger
+#endif
+void InitLogging(char* argv[],
+ LogFunction&& logger = INIT_LOGGING_DEFAULT_LOGGER,
+ AbortFunction&& aborter = DefaultAborter);
+#undef INIT_LOGGING_DEFAULT_LOGGER
+
+// Replace the current logger.
+void SetLogger(LogFunction&& logger);
+
+// Replace the current aborter.
+void SetAborter(AbortFunction&& aborter);
+
+class ErrnoRestorer {
+ public:
+ ErrnoRestorer()
+ : saved_errno_(errno) {
+ }
+
+ ~ErrnoRestorer() {
+ errno = saved_errno_;
+ }
+
+ // Allow this object to be used as part of && operation.
+ operator bool() const {
+ return true;
+ }
+
+ private:
+ const int saved_errno_;
+
+ DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
+};
+
+// A helper macro that produces an expression that accepts both a qualified name and an
+// unqualified name for a LogSeverity, and returns a LogSeverity value.
+// Note: DO NOT USE DIRECTLY. This is an implementation detail.
+#define SEVERITY_LAMBDA(severity) ([&]() { \
+ using ::android::base::VERBOSE; \
+ using ::android::base::DEBUG; \
+ using ::android::base::INFO; \
+ using ::android::base::WARNING; \
+ using ::android::base::ERROR; \
+ using ::android::base::FATAL_WITHOUT_ABORT; \
+ using ::android::base::FATAL; \
+ return (severity); }())
+
+#ifdef __clang_analyzer__
+// Clang's static analyzer does not see the conditional statement inside
+// LogMessage's destructor that will abort on FATAL severity.
+#define ABORT_AFTER_LOG_FATAL for (;; abort())
+
+struct LogAbortAfterFullExpr {
+ ~LogAbortAfterFullExpr() __attribute__((noreturn)) { abort(); }
+ explicit operator bool() const { return false; }
+};
+// Provides an expression that evaluates to the truthiness of `x`, automatically
+// aborting if `c` is true.
+#define ABORT_AFTER_LOG_EXPR_IF(c, x) (((c) && ::android::base::LogAbortAfterFullExpr()) || (x))
+// Note to the static analyzer that we always execute FATAL logs in practice.
+#define MUST_LOG_MESSAGE(severity) (SEVERITY_LAMBDA(severity) == ::android::base::FATAL)
+#else
+#define ABORT_AFTER_LOG_FATAL
+#define ABORT_AFTER_LOG_EXPR_IF(c, x) (x)
+#define MUST_LOG_MESSAGE(severity) false
+#endif
+#define ABORT_AFTER_LOG_FATAL_EXPR(x) ABORT_AFTER_LOG_EXPR_IF(true, x)
+
+// Defines whether the given severity will be logged or silently swallowed.
+#define WOULD_LOG(severity) \
+ (UNLIKELY((SEVERITY_LAMBDA(severity)) >= ::android::base::GetMinimumLogSeverity()) || \
+ MUST_LOG_MESSAGE(severity))
+
+// Get an ostream that can be used for logging at the given severity and to the default
+// destination.
+//
+// Notes:
+// 1) This will not check whether the severity is high enough. One should use WOULD_LOG to filter
+// usage manually.
+// 2) This does not save and restore errno.
+#define LOG_STREAM(severity) LOG_STREAM_TO(DEFAULT, severity)
+
+// Get an ostream that can be used for logging at the given severity and to the
+// given destination. The same notes as for LOG_STREAM apply.
+#define LOG_STREAM_TO(dest, severity) \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \
+ SEVERITY_LAMBDA(severity), _LOG_TAG_INTERNAL, -1) \
+ .stream()
+
+// Logs a message to logcat on Android otherwise to stderr. If the severity is
+// FATAL it also causes an abort. For example:
+//
+// LOG(FATAL) << "We didn't expect to reach here";
+#define LOG(severity) LOG_TO(DEFAULT, severity)
+
+// Checks if we want to log something, and sets up appropriate RAII objects if
+// so.
+// Note: DO NOT USE DIRECTLY. This is an implementation detail.
+#define LOGGING_PREAMBLE(severity) \
+ (WOULD_LOG(severity) && \
+ ABORT_AFTER_LOG_EXPR_IF((SEVERITY_LAMBDA(severity)) == ::android::base::FATAL, true) && \
+ ::android::base::ErrnoRestorer())
+
+// Logs a message to logcat with the specified log ID on Android otherwise to
+// stderr. If the severity is FATAL it also causes an abort.
+// Use an expression here so we can support the << operator following the macro,
+// like "LOG(DEBUG) << xxx;".
+#define LOG_TO(dest, severity) LOGGING_PREAMBLE(severity) && LOG_STREAM_TO(dest, severity)
+
+// A variant of LOG that also logs the current errno value. To be used when
+// library calls fail.
+#define PLOG(severity) PLOG_TO(DEFAULT, severity)
+
+// Behaves like PLOG, but logs to the specified log ID.
+#define PLOG_TO(dest, severity) \
+ LOGGING_PREAMBLE(severity) && \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \
+ SEVERITY_LAMBDA(severity), _LOG_TAG_INTERNAL, errno) \
+ .stream()
+
+// Marker that code is yet to be implemented.
+#define UNIMPLEMENTED(level) \
+ LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
+
+// Check whether condition x holds and LOG(FATAL) if not. The value of the
+// expression x is only evaluated once. Extra logging can be appended using <<
+// after. For example:
+//
+// CHECK(false == true) results in a log message of
+// "Check failed: false == true".
+#define CHECK(x) \
+ LIKELY((x)) || ABORT_AFTER_LOG_FATAL_EXPR(false) || \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::FATAL, _LOG_TAG_INTERNAL, -1) \
+ .stream() \
+ << "Check failed: " #x << " "
+
+// clang-format off
+// Helper for CHECK_xx(x,y) macros.
+#define CHECK_OP(LHS, RHS, OP) \
+ for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS); \
+ UNLIKELY(!(_values.lhs OP _values.rhs)); \
+ /* empty */) \
+ ABORT_AFTER_LOG_FATAL \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::FATAL, _LOG_TAG_INTERNAL, -1) \
+ .stream() \
+ << "Check failed: " << #LHS << " " << #OP << " " << #RHS << " (" #LHS "=" << _values.lhs \
+ << ", " #RHS "=" << _values.rhs << ") "
+// clang-format on
+
+// Check whether a condition holds between x and y, LOG(FATAL) if not. The value
+// of the expressions x and y is evaluated once. Extra logging can be appended
+// using << after. For example:
+//
+// CHECK_NE(0 == 1, false) results in
+// "Check failed: false != false (0==1=false, false=false) ".
+#define CHECK_EQ(x, y) CHECK_OP(x, y, == )
+#define CHECK_NE(x, y) CHECK_OP(x, y, != )
+#define CHECK_LE(x, y) CHECK_OP(x, y, <= )
+#define CHECK_LT(x, y) CHECK_OP(x, y, < )
+#define CHECK_GE(x, y) CHECK_OP(x, y, >= )
+#define CHECK_GT(x, y) CHECK_OP(x, y, > )
+
+// clang-format off
+// Helper for CHECK_STRxx(s1,s2) macros.
+#define CHECK_STROP(s1, s2, sense) \
+ while (UNLIKELY((strcmp(s1, s2) == 0) != (sense))) \
+ ABORT_AFTER_LOG_FATAL \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::FATAL, _LOG_TAG_INTERNAL, -1) \
+ .stream() \
+ << "Check failed: " << "\"" << (s1) << "\"" \
+ << ((sense) ? " == " : " != ") << "\"" << (s2) << "\""
+// clang-format on
+
+// Check for string (const char*) equality between s1 and s2, LOG(FATAL) if not.
+#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
+#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
+
+// Perform the pthread function call(args), LOG(FATAL) on error.
+#define CHECK_PTHREAD_CALL(call, args, what) \
+ do { \
+ int rc = call args; \
+ if (rc != 0) { \
+ errno = rc; \
+ ABORT_AFTER_LOG_FATAL \
+ PLOG(FATAL) << #call << " failed for " << (what); \
+ } \
+ } while (false)
+
+// CHECK that can be used in a constexpr function. For example:
+//
+// constexpr int half(int n) {
+// return
+// DCHECK_CONSTEXPR(n >= 0, , 0)
+// CHECK_CONSTEXPR((n & 1) == 0),
+// << "Extra debugging output: n = " << n, 0)
+// n / 2;
+// }
+#define CHECK_CONSTEXPR(x, out, dummy) \
+ (UNLIKELY(!(x))) \
+ ? (LOG(FATAL) << "Check failed: " << #x out, dummy) \
+ :
+
+// DCHECKs are debug variants of CHECKs only enabled in debug builds. Generally
+// CHECK should be used unless profiling identifies a CHECK as being in
+// performance critical code.
+#if defined(NDEBUG) && !defined(__clang_analyzer__)
+static constexpr bool kEnableDChecks = false;
+#else
+static constexpr bool kEnableDChecks = true;
+#endif
+
+#define DCHECK(x) \
+ if (::android::base::kEnableDChecks) CHECK(x)
+#define DCHECK_EQ(x, y) \
+ if (::android::base::kEnableDChecks) CHECK_EQ(x, y)
+#define DCHECK_NE(x, y) \
+ if (::android::base::kEnableDChecks) CHECK_NE(x, y)
+#define DCHECK_LE(x, y) \
+ if (::android::base::kEnableDChecks) CHECK_LE(x, y)
+#define DCHECK_LT(x, y) \
+ if (::android::base::kEnableDChecks) CHECK_LT(x, y)
+#define DCHECK_GE(x, y) \
+ if (::android::base::kEnableDChecks) CHECK_GE(x, y)
+#define DCHECK_GT(x, y) \
+ if (::android::base::kEnableDChecks) CHECK_GT(x, y)
+#define DCHECK_STREQ(s1, s2) \
+ if (::android::base::kEnableDChecks) CHECK_STREQ(s1, s2)
+#define DCHECK_STRNE(s1, s2) \
+ if (::android::base::kEnableDChecks) CHECK_STRNE(s1, s2)
+#if defined(NDEBUG) && !defined(__clang_analyzer__)
+#define DCHECK_CONSTEXPR(x, out, dummy)
+#else
+#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy)
+#endif
+
+// Temporary class created to evaluate the LHS and RHS, used with
+// MakeEagerEvaluator to infer the types of LHS and RHS.
+template <typename LHS, typename RHS>
+struct EagerEvaluator {
+ constexpr EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) {
+ }
+ LHS lhs;
+ RHS rhs;
+};
+
+// Helper function for CHECK_xx.
+template <typename LHS, typename RHS>
+constexpr EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
+ return EagerEvaluator<LHS, RHS>(lhs, rhs);
+}
+
+// Explicitly instantiate EagerEvalue for pointers so that char*s aren't treated
+// as strings. To compare strings use CHECK_STREQ and CHECK_STRNE. We rely on
+// signed/unsigned warnings to protect you against combinations not explicitly
+// listed below.
+#define EAGER_PTR_EVALUATOR(T1, T2) \
+ template <> \
+ struct EagerEvaluator<T1, T2> { \
+ EagerEvaluator(T1 l, T2 r) \
+ : lhs(reinterpret_cast<const void*>(l)), \
+ rhs(reinterpret_cast<const void*>(r)) { \
+ } \
+ const void* lhs; \
+ const void* rhs; \
+ }
+EAGER_PTR_EVALUATOR(const char*, const char*);
+EAGER_PTR_EVALUATOR(const char*, char*);
+EAGER_PTR_EVALUATOR(char*, const char*);
+EAGER_PTR_EVALUATOR(char*, char*);
+EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*);
+EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*);
+EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*);
+EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*);
+EAGER_PTR_EVALUATOR(const signed char*, const signed char*);
+EAGER_PTR_EVALUATOR(const signed char*, signed char*);
+EAGER_PTR_EVALUATOR(signed char*, const signed char*);
+EAGER_PTR_EVALUATOR(signed char*, signed char*);
+
+// Data for the log message, not stored in LogMessage to avoid increasing the
+// stack size.
+class LogMessageData;
+
+// A LogMessage is a temporarily scoped object used by LOG and the unlikely part
+// of a CHECK. The destructor will abort if the severity is FATAL.
+class LogMessage {
+ public:
+ LogMessage(const char* file, unsigned int line, LogId id, LogSeverity severity, const char* tag,
+ int error);
+
+ ~LogMessage();
+
+ // Returns the stream associated with the message, the LogMessage performs
+ // output when it goes out of scope.
+ std::ostream& stream();
+
+ // The routine that performs the actual logging.
+ static void LogLine(const char* file, unsigned int line, LogId id, LogSeverity severity,
+ const char* tag, const char* msg);
+
+ private:
+ const std::unique_ptr<LogMessageData> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(LogMessage);
+};
+
+// Get the minimum severity level for logging.
+LogSeverity GetMinimumLogSeverity();
+
+// Set the minimum severity level for logging, returning the old severity.
+LogSeverity SetMinimumLogSeverity(LogSeverity new_severity);
+
+// Allows to temporarily change the minimum severity level for logging.
+class ScopedLogSeverity {
+ public:
+ explicit ScopedLogSeverity(LogSeverity level);
+ ~ScopedLogSeverity();
+
+ private:
+ LogSeverity old_;
+};
+
+} // namespace base
+} // namespace android
+
+namespace std {
+
+// Emit a warning of ostream<< with std::string*. The intention was most likely to print *string.
+//
+// Note: for this to work, we need to have this in a namespace.
+// Note: lots of ifdef magic to make this work with Clang (platform) vs GCC (windows tools)
+// Note: using diagnose_if(true) under Clang and nothing under GCC/mingw as there is no common
+// attribute support.
+// Note: using a pragma because "-Wgcc-compat" (included in "-Weverything") complains about
+// diagnose_if.
+// Note: to print the pointer, use "<< static_cast<const void*>(string_pointer)" instead.
+// Note: a not-recommended alternative is to let Clang ignore the warning by adding
+// -Wno-user-defined-warnings to CPPFLAGS.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgcc-compat"
+#define OSTREAM_STRING_POINTER_USAGE_WARNING \
+ __attribute__((diagnose_if(true, "Unexpected logging of string pointer", "warning")))
+inline std::ostream& operator<<(std::ostream& stream, const std::string* string_pointer)
+ OSTREAM_STRING_POINTER_USAGE_WARNING {
+ return stream << static_cast<const void*>(string_pointer);
+}
+#pragma clang diagnostic pop
+
+} // namespace std
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/macros.h
^
|
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stddef.h> // for size_t
+#include <unistd.h> // for TEMP_FAILURE_RETRY
+
+#include <utility>
+
+// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't.
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ decltype(exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; \
+ })
+#endif
+
+// A macro to disallow the copy constructor and operator= functions
+// This must be placed in the private: declarations for a class.
+//
+// For disallowing only assign or copy, delete the relevant operator or
+// constructor, for example:
+// void operator=(const TypeName&) = delete;
+// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
+// semantically, one should either use disallow both or neither. Try to
+// avoid these in new code.
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName() = delete; \
+ DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// The arraysize(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example. If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that arraysize() doesn't accept any array of an
+// anonymous type or a type defined inside a function. In these rare
+// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
+// due to a limitation in C++'s template system. The limitation might
+// eventually be removed, but it hasn't happened yet.
+
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char(&ArraySizeHelper(T(&array)[N]))[N]; // NOLINT(readability/casting)
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
+#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)
+
+// Changing this definition will cause you a lot of pain. A majority of
+// vendor code defines LIKELY and UNLIKELY this way, and includes
+// this header through an indirect path.
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+#define WARN_UNUSED __attribute__((warn_unused_result))
+
+// A deprecated function to call to create a false use of the parameter, for
+// example:
+// int foo(int x) { UNUSED(x); return 10; }
+// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED.
+template <typename... T>
+void UNUSED(const T&...) {
+}
+
+// An attribute to place on a parameter to a function, for example:
+// int foo(int x ATTRIBUTE_UNUSED) { return 10; }
+// to avoid compiler warnings.
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+
+// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
+// between switch labels:
+// switch (x) {
+// case 40:
+// case 41:
+// if (truth_is_out_there) {
+// ++x;
+// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in
+// // comments.
+// } else {
+// return x;
+// }
+// case 42:
+// ...
+//
+// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+// followed by a semicolon. It is designed to mimic control-flow statements
+// like 'break;', so it can be placed in most places where 'break;' can, but
+// only if there are no statements on the execution path between it and the
+// next switch label.
+//
+// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
+// [[clang::fallthrough]] attribute, which is analysed when performing switch
+// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
+// documentation on language extensions for details:
+// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+//
+// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+// effect on diagnostics.
+//
+// In either case this macro has no effect on runtime behavior and performance
+// of code.
+#ifndef FALLTHROUGH_INTENDED
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT
+#endif
+
+// Current ABI string
+#if defined(__arm__)
+#define ABI_STRING "arm"
+#elif defined(__aarch64__)
+#define ABI_STRING "arm64"
+#elif defined(__i386__)
+#define ABI_STRING "x86"
+#elif defined(__x86_64__)
+#define ABI_STRING "x86_64"
+#elif defined(__mips__) && !defined(__LP64__)
+#define ABI_STRING "mips"
+#elif defined(__mips__) && defined(__LP64__)
+#define ABI_STRING "mips64"
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/mapped_file.h
^
|
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "android-base/macros.h"
+#include "android-base/off64_t.h"
+
+#include <sys/types.h>
+
+#include <memory>
+
+#if defined(_WIN32)
+#include <windows.h>
+#define PROT_READ 1
+#define PROT_WRITE 2
+#else
+#include <sys/mman.h>
+#endif
+
+namespace android {
+namespace base {
+
+/**
+ * A region of a file mapped into memory.
+ */
+class MappedFile {
+ public:
+ /**
+ * Creates a new mapping of the file pointed to by `fd`. Unlike the underlying OS primitives,
+ * `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping
+ * will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`.
+ */
+ static std::unique_ptr<MappedFile> FromFd(int fd, off64_t offset, size_t length, int prot);
+
+ /**
+ * Removes the mapping.
+ */
+ ~MappedFile();
+
+ char* data() { return base_ + offset_; }
+ size_t size() { return size_; }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
+
+ char* base_;
+ size_t size_;
+
+ size_t offset_;
+
+#if defined(_WIN32)
+ MappedFile(char* base, size_t size, size_t offset, HANDLE handle)
+ : base_(base), size_(size), offset_(offset), handle_(handle) {}
+ HANDLE handle_;
+#else
+ MappedFile(char* base, size_t size, size_t offset) : base_(base), size_(size), offset_(offset) {}
+#endif
+};
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/memory.h
^
|
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android {
+namespace base {
+
+// Use memcpy for access to unaligned data on targets with alignment
+// restrictions. The compiler will generate appropriate code to access these
+// structures without generating alignment exceptions.
+template <typename T>
+static inline T get_unaligned(const void* address) {
+ T result;
+ memcpy(&result, address, sizeof(T));
+ return result;
+}
+
+template <typename T>
+static inline void put_unaligned(void* address, T v) {
+ memcpy(address, &v, sizeof(T));
+}
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/off64_t.h
^
|
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if defined(__APPLE__)
+/** Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
+typedef off_t off64_t;
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/parsedouble.h
^
|
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <limits>
+#include <string>
+
+namespace android {
+namespace base {
+
+// Parse floating value in the string 's' and sets 'out' to that value if it exists.
+// Optionally allows the caller to define a 'min' and 'max' beyond which
+// otherwise valid values will be rejected. Returns boolean success.
+template <typename T, T (*strtox)(const char* str, char** endptr)>
+static inline bool ParseFloatingPoint(const char* s, T* out, T min, T max) {
+ errno = 0;
+ char* end;
+ T result = strtox(s, &end);
+ if (errno != 0 || s == end || *end != '\0') {
+ return false;
+ }
+ if (result < min || max < result) {
+ return false;
+ }
+ if (out != nullptr) {
+ *out = result;
+ }
+ return true;
+}
+
+// Parse double value in the string 's' and sets 'out' to that value if it exists.
+// Optionally allows the caller to define a 'min' and 'max' beyond which
+// otherwise valid values will be rejected. Returns boolean success.
+static inline bool ParseDouble(const char* s, double* out,
+ double min = std::numeric_limits<double>::lowest(),
+ double max = std::numeric_limits<double>::max()) {
+ return ParseFloatingPoint<double, strtod>(s, out, min, max);
+}
+static inline bool ParseDouble(const std::string& s, double* out,
+ double min = std::numeric_limits<double>::lowest(),
+ double max = std::numeric_limits<double>::max()) {
+ return ParseFloatingPoint<double, strtod>(s.c_str(), out, min, max);
+}
+
+// Parse float value in the string 's' and sets 'out' to that value if it exists.
+// Optionally allows the caller to define a 'min' and 'max' beyond which
+// otherwise valid values will be rejected. Returns boolean success.
+static inline bool ParseFloat(const char* s, float* out,
+ float min = std::numeric_limits<float>::lowest(),
+ float max = std::numeric_limits<float>::max()) {
+ return ParseFloatingPoint<float, strtof>(s, out, min, max);
+}
+static inline bool ParseFloat(const std::string& s, float* out,
+ float min = std::numeric_limits<float>::lowest(),
+ float max = std::numeric_limits<float>::max()) {
+ return ParseFloatingPoint<float, strtof>(s.c_str(), out, min, max);
+}
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/parseint.h
^
|
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <limits>
+#include <string>
+#include <type_traits>
+
+namespace android {
+namespace base {
+
+// Parses the unsigned decimal or hexadecimal integer in the string 's' and sets
+// 'out' to that value if it is specified. Optionally allows the caller to define
+// a 'max' beyond which otherwise valid values will be rejected. Returns boolean
+// success; 'out' is untouched if parsing fails.
+template <typename T>
+bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
+ bool allow_suffixes = false) {
+ static_assert(std::is_unsigned<T>::value, "ParseUint can only be used with unsigned types");
+ while (isspace(*s)) {
+ s++;
+ }
+
+ if (s[0] == '-') {
+ errno = EINVAL;
+ return false;
+ }
+
+ int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
+ errno = 0;
+ char* end;
+ unsigned long long int result = strtoull(s, &end, base);
+ if (errno != 0) return false;
+ if (end == s) {
+ errno = EINVAL;
+ return false;
+ }
+ if (*end != '\0') {
+ const char* suffixes = "bkmgtpe";
+ const char* suffix;
+ if ((!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) ||
+ __builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) {
+ errno = EINVAL;
+ return false;
+ }
+ }
+ if (max < result) {
+ errno = ERANGE;
+ return false;
+ }
+ if (out != nullptr) {
+ *out = static_cast<T>(result);
+ }
+ return true;
+}
+
+// TODO: string_view
+template <typename T>
+bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
+ bool allow_suffixes = false) {
+ return ParseUint(s.c_str(), out, max, allow_suffixes);
+}
+
+template <typename T>
+bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
+ return ParseUint(s, out, max, true);
+}
+
+// TODO: string_view
+template <typename T>
+bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
+ return ParseByteCount(s.c_str(), out, max);
+}
+
+// Parses the signed decimal or hexadecimal integer in the string 's' and sets
+// 'out' to that value if it is specified. Optionally allows the caller to define
+// a 'min' and 'max' beyond which otherwise valid values will be rejected. Returns
+// boolean success; 'out' is untouched if parsing fails.
+template <typename T>
+bool ParseInt(const char* s, T* out,
+ T min = std::numeric_limits<T>::min(),
+ T max = std::numeric_limits<T>::max()) {
+ static_assert(std::is_signed<T>::value, "ParseInt can only be used with signed types");
+ while (isspace(*s)) {
+ s++;
+ }
+
+ int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
+ errno = 0;
+ char* end;
+ long long int result = strtoll(s, &end, base);
+ if (errno != 0) {
+ return false;
+ }
+ if (s == end || *end != '\0') {
+ errno = EINVAL;
+ return false;
+ }
+ if (result < min || max < result) {
+ errno = ERANGE;
+ return false;
+ }
+ if (out != nullptr) {
+ *out = static_cast<T>(result);
+ }
+ return true;
+}
+
+// TODO: string_view
+template <typename T>
+bool ParseInt(const std::string& s, T* out,
+ T min = std::numeric_limits<T>::min(),
+ T max = std::numeric_limits<T>::max()) {
+ return ParseInt(s.c_str(), out, min, max);
+}
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/parsenetaddress.h
^
|
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace android {
+namespace base {
+
+// Parses |address| into |host| and |port|.
+//
+// If |address| doesn't contain a port number, the default value is taken from
+// |port|. If |canonical_address| is non-null it will be set to "host:port" or
+// "[host]:port" as appropriate.
+//
+// On failure, returns false and fills |error|.
+bool ParseNetAddress(const std::string& address, std::string* host, int* port,
+ std::string* canonical_address, std::string* error);
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/properties.h
^
|
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#include <chrono>
+#include <limits>
+#include <string>
+
+namespace android {
+namespace base {
+
+// Returns the current value of the system property `key`,
+// or `default_value` if the property is empty or doesn't exist.
+std::string GetProperty(const std::string& key, const std::string& default_value);
+
+// Returns true if the system property `key` has the value "1", "y", "yes", "on", or "true",
+// false for "0", "n", "no", "off", or "false", or `default_value` otherwise.
+bool GetBoolProperty(const std::string& key, bool default_value);
+
+// Returns the signed integer corresponding to the system property `key`.
+// If the property is empty, doesn't exist, doesn't have an integer value, or is outside
+// the optional bounds, returns `default_value`.
+template <typename T> T GetIntProperty(const std::string& key,
+ T default_value,
+ T min = std::numeric_limits<T>::min(),
+ T max = std::numeric_limits<T>::max());
+
+// Returns the unsigned integer corresponding to the system property `key`.
+// If the property is empty, doesn't exist, doesn't have an integer value, or is outside
+// the optional bound, returns `default_value`.
+template <typename T> T GetUintProperty(const std::string& key,
+ T default_value,
+ T max = std::numeric_limits<T>::max());
+
+// Sets the system property `key` to `value`.
+// Note that system property setting is inherently asynchronous so a return value of `true`
+// isn't particularly meaningful, and immediately reading back the value won't necessarily
+// tell you whether or not your call succeeded. A `false` return value definitely means failure.
+bool SetProperty(const std::string& key, const std::string& value);
+
+// Waits for the system property `key` to have the value `expected_value`.
+// Times out after `relative_timeout`.
+// Returns true on success, false on timeout.
+#if defined(__BIONIC__)
+bool WaitForProperty(const std::string& key, const std::string& expected_value,
+ std::chrono::milliseconds relative_timeout = std::chrono::milliseconds::max());
+#endif
+
+// Waits for the system property `key` to be created.
+// Times out after `relative_timeout`.
+// Returns true on success, false on timeout.
+#if defined(__BIONIC__)
+bool WaitForPropertyCreation(const std::string& key, std::chrono::milliseconds relative_timeout =
+ std::chrono::milliseconds::max());
+#endif
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/quick_exit.h
^
|
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+
+// Provide emulation for at_quick_exit/quick_exit on platforms that don't have it.
+namespace android {
+namespace base {
+
+// Bionic and glibc have quick_exit, Darwin and Windows don't.
+#if !defined(__linux__)
+ void quick_exit(int exit_code) __attribute__((noreturn));
+ int at_quick_exit(void (*func)());
+#else
+ using ::at_quick_exit;
+ using ::quick_exit;
+#endif
+}
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/scopeguard.h
^
|
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utility> // for std::move, std::forward
+
+namespace android {
+namespace base {
+
+// ScopeGuard ensures that the specified functor is executed no matter how the
+// current scope exits.
+template <typename F>
+class ScopeGuard {
+ public:
+ ScopeGuard(F&& f) : f_(std::forward<F>(f)), active_(true) {}
+
+ ScopeGuard(ScopeGuard&& that) noexcept : f_(std::move(that.f_)), active_(that.active_) {
+ that.active_ = false;
+ }
+
+ template <typename Functor>
+ ScopeGuard(ScopeGuard<Functor>&& that) : f_(std::move(that.f_)), active_(that.active_) {
+ that.active_ = false;
+ }
+
+ ~ScopeGuard() {
+ if (active_) f_();
+ }
+
+ ScopeGuard() = delete;
+ ScopeGuard(const ScopeGuard&) = delete;
+ void operator=(const ScopeGuard&) = delete;
+ void operator=(ScopeGuard&& that) = delete;
+
+ void Disable() { active_ = false; }
+
+ bool active() const { return active_; }
+
+ private:
+ template <typename Functor>
+ friend class ScopeGuard;
+
+ F f_;
+ bool active_;
+};
+
+template <typename F>
+ScopeGuard<F> make_scope_guard(F&& f) {
+ return ScopeGuard<F>(std::forward<F>(f));
+}
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/stringprintf.h
^
|
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdarg.h>
+#include <string>
+
+namespace android {
+namespace base {
+
+// These printf-like functions are implemented in terms of vsnprintf, so they
+// use the same attribute for compile-time format string checking.
+
+// Returns a string corresponding to printf-like formatting of the arguments.
+std::string StringPrintf(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
+
+// Appends a printf-like formatting of the arguments to 'dst'.
+void StringAppendF(std::string* dst, const char* fmt, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+
+// Appends a printf-like formatting of the arguments to 'dst'.
+void StringAppendV(std::string* dst, const char* format, va_list ap)
+ __attribute__((__format__(__printf__, 2, 0)));
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/strings.h
^
|
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace base {
+
+// Splits a string into a vector of strings.
+//
+// The string is split at each occurrence of a character in delimiters.
+//
+// The empty string is not a valid delimiter list.
+std::vector<std::string> Split(const std::string& s,
+ const std::string& delimiters);
+
+// Trims whitespace off both ends of the given string.
+std::string Trim(const std::string& s);
+
+// Joins a container of things into a single string, using the given separator.
+template <typename ContainerT, typename SeparatorT>
+std::string Join(const ContainerT& things, SeparatorT separator) {
+ if (things.empty()) {
+ return "";
+ }
+
+ std::ostringstream result;
+ result << *things.begin();
+ for (auto it = std::next(things.begin()); it != things.end(); ++it) {
+ result << separator << *it;
+ }
+ return result.str();
+}
+
+// We instantiate the common cases in strings.cpp.
+extern template std::string Join(const std::vector<std::string>&, char);
+extern template std::string Join(const std::vector<const char*>&, char);
+extern template std::string Join(const std::vector<std::string>&, const std::string&);
+extern template std::string Join(const std::vector<const char*>&, const std::string&);
+
+// Tests whether 's' starts with 'prefix'.
+bool StartsWith(std::string_view s, std::string_view prefix);
+bool StartsWith(std::string_view s, char prefix);
+bool StartsWithIgnoreCase(std::string_view s, std::string_view prefix);
+
+// Tests whether 's' ends with 'suffix'.
+bool EndsWith(std::string_view s, std::string_view suffix);
+bool EndsWith(std::string_view s, char suffix);
+bool EndsWithIgnoreCase(std::string_view s, std::string_view suffix);
+
+// Tests whether 'lhs' equals 'rhs', ignoring case.
+bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs);
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/test_utils.h
^
|
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <regex>
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+
+class CapturedStdFd {
+ public:
+ CapturedStdFd(int std_fd);
+ ~CapturedStdFd();
+
+ std::string str();
+
+ void Start();
+ void Stop();
+ void Reset();
+
+ private:
+ int fd() const;
+
+ TemporaryFile temp_file_;
+ int std_fd_;
+ int old_fd_ = -1;
+
+ DISALLOW_COPY_AND_ASSIGN(CapturedStdFd);
+};
+
+class CapturedStderr : public CapturedStdFd {
+ public:
+ CapturedStderr() : CapturedStdFd(STDERR_FILENO) {}
+};
+
+class CapturedStdout : public CapturedStdFd {
+ public:
+ CapturedStdout() : CapturedStdFd(STDOUT_FILENO) {}
+};
+
+#define ASSERT_MATCH(str, pattern) \
+ do { \
+ if (!std::regex_search((str), std::regex((pattern)))) { \
+ FAIL() << "regex mismatch: expected " << (pattern) << " in:\n" << (str); \
+ } \
+ } while (0)
+
+#define ASSERT_NOT_MATCH(str, pattern) \
+ do { \
+ if (std::regex_search((str), std::regex((pattern)))) { \
+ FAIL() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
+ } \
+ } while (0)
+
+#define EXPECT_MATCH(str, pattern) \
+ do { \
+ if (!std::regex_search((str), std::regex((pattern)))) { \
+ ADD_FAILURE() << "regex mismatch: expected " << (pattern) << " in:\n" << (str); \
+ } \
+ } while (0)
+
+#define EXPECT_NOT_MATCH(str, pattern) \
+ do { \
+ if (std::regex_search((str), std::regex((pattern)))) { \
+ ADD_FAILURE() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
+ } \
+ } while (0)
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/thread_annotations.h
^
|
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+
+#define CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+
+#define SCOPED_CAPABILITY \
+ THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define SHARED_CAPABILITY(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_capability(__VA_ARGS__))
+
+#define GUARDED_BY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+
+#define PT_GUARDED_BY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+
+#define EXCLUSIVE_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
+
+#define SHARED_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
+
+#define ACQUIRED_BEFORE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+
+#define ACQUIRED_AFTER(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+#define REQUIRES(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+
+#define REQUIRES_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+
+#define ACQUIRE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+
+#define ACQUIRE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+
+#define RELEASE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+
+#define RELEASE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+
+#define TRY_ACQUIRE_SHARED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+
+#define EXCLUDES(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+#define ASSERT_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+
+#define ASSERT_SHARED_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+
+#define RETURN_CAPABILITY(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+#define EXCLUSIVE_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
+
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
+
+#define SHARED_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
+
+#define SHARED_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
+
+#define UNLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
+
+#define SCOPED_LOCKABLE \
+ THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define LOCK_RETURNED(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+#define NO_THREAD_SAFETY_ANALYSIS \
+ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+
+namespace android {
+namespace base {
+
+// A class to help thread safety analysis deal with std::unique_lock and condition_variable.
+//
+// Clang's thread safety analysis currently doesn't perform alias analysis, so movable types
+// like std::unique_lock can't be marked with thread safety annotations. This helper allows
+// for manual assertion of lock state in a scope.
+//
+// For example:
+//
+// std::mutex mutex;
+// std::condition_variable cv;
+// std::vector<int> vec GUARDED_BY(mutex);
+//
+// int pop() {
+// std::unique_lock lock(mutex);
+// ScopedLockAssertion lock_assertion(mutex);
+// cv.wait(lock, []() {
+// ScopedLockAssertion lock_assertion(mutex);
+// return !vec.empty();
+// });
+//
+// int result = vec.back();
+// vec.pop_back();
+// return result;
+// }
+class SCOPED_CAPABILITY ScopedLockAssertion {
+ public:
+ ScopedLockAssertion(std::mutex& mutex) ACQUIRE(mutex) {}
+ ~ScopedLockAssertion() RELEASE() {}
+};
+
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/threads.h
^
|
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+namespace android {
+namespace base {
+uint64_t GetThreadId();
+}
+} // namespace android
+
+#if defined(__GLIBC__)
+// bionic has this Linux-specifix call, but glibc doesn't.
+extern "C" int tgkill(int tgid, int tid, int sig);
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/unique_fd.h
^
|
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if !defined(_WIN32)
+#include <sys/socket.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// DO NOT INCLUDE OTHER LIBBASE HEADERS!
+// This file gets used in libbinder, and libbinder is used everywhere.
+// Including other headers from libbase frequently results in inclusion of
+// android-base/macros.h, which causes macro collisions.
+
+// Container for a file descriptor that automatically closes the descriptor as
+// it goes out of scope.
+//
+// unique_fd ufd(open("/some/path", "r"));
+// if (ufd.get() == -1) return error;
+//
+// // Do something useful, possibly including 'return'.
+//
+// return 0; // Descriptor is closed for you.
+//
+// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
+// you find this class if you're searching for one of those names.
+
+#if defined(__BIONIC__)
+#include <android/fdsan.h>
+#endif
+
+namespace android {
+namespace base {
+
+struct DefaultCloser {
+#if defined(__BIONIC__)
+ static void Tag(int fd, void* old_addr, void* new_addr) {
+ if (android_fdsan_exchange_owner_tag) {
+ uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+ reinterpret_cast<uint64_t>(old_addr));
+ uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+ reinterpret_cast<uint64_t>(new_addr));
+ android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
+ }
+ }
+ static void Close(int fd, void* addr) {
+ if (android_fdsan_close_with_tag) {
+ uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+ reinterpret_cast<uint64_t>(addr));
+ android_fdsan_close_with_tag(fd, tag);
+ } else {
+ close(fd);
+ }
+ }
+#else
+ static void Close(int fd) {
+ // Even if close(2) fails with EINTR, the fd will have been closed.
+ // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
+ // else's fd.
+ // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+ ::close(fd);
+ }
+#endif
+};
+
+template <typename Closer>
+class unique_fd_impl final {
+ public:
+ unique_fd_impl() {}
+
+ explicit unique_fd_impl(int fd) { reset(fd); }
+ ~unique_fd_impl() { reset(); }
+
+ unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); }
+ unique_fd_impl& operator=(unique_fd_impl&& s) noexcept {
+ int fd = s.fd_;
+ s.fd_ = -1;
+ reset(fd, &s);
+ return *this;
+ }
+
+ void reset(int new_value = -1) { reset(new_value, nullptr); }
+
+ int get() const { return fd_; }
+ operator int() const { return get(); } // NOLINT
+
+ // Catch bogus error checks (i.e.: "!fd" instead of "fd != -1").
+ bool operator!() const = delete;
+
+ int release() __attribute__((warn_unused_result)) {
+ tag(fd_, this, nullptr);
+ int ret = fd_;
+ fd_ = -1;
+ return ret;
+ }
+
+ private:
+ void reset(int new_value, void* previous_tag) {
+ int previous_errno = errno;
+
+ if (fd_ != -1) {
+ close(fd_, this);
+ }
+
+ fd_ = new_value;
+ if (new_value != -1) {
+ tag(new_value, previous_tag, this);
+ }
+
+ errno = previous_errno;
+ }
+
+ int fd_ = -1;
+
+ // Template magic to use Closer::Tag if available, and do nothing if not.
+ // If Closer::Tag exists, this implementation is preferred, because int is a better match.
+ // If not, this implementation is SFINAEd away, and the no-op below is the only one that exists.
+ template <typename T = Closer>
+ static auto tag(int fd, void* old_tag, void* new_tag)
+ -> decltype(T::Tag(fd, old_tag, new_tag), void()) {
+ T::Tag(fd, old_tag, new_tag);
+ }
+
+ template <typename T = Closer>
+ static void tag(long, void*, void*) {
+ // No-op.
+ }
+
+ // Same as above, to select between Closer::Close(int) and Closer::Close(int, void*).
+ template <typename T = Closer>
+ static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) {
+ T::Close(fd, tag_value);
+ }
+
+ template <typename T = Closer>
+ static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
+ T::Close(fd);
+ }
+
+ unique_fd_impl(const unique_fd_impl&);
+ void operator=(const unique_fd_impl&);
+};
+
+using unique_fd = unique_fd_impl<DefaultCloser>;
+
+#if !defined(_WIN32)
+
+// Inline functions, so that they can be used header-only.
+template <typename Closer>
+inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
+ int flags = O_CLOEXEC) {
+ int pipefd[2];
+
+#if defined(__linux__)
+ if (pipe2(pipefd, flags) != 0) {
+ return false;
+ }
+#else // defined(__APPLE__)
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK)) {
+ return false;
+ }
+ if (pipe(pipefd) != 0) {
+ return false;
+ }
+
+ if (flags & O_CLOEXEC) {
+ if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return false;
+ }
+ }
+ if (flags & O_NONBLOCK) {
+ if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return false;
+ }
+ }
+#endif
+
+ read->reset(pipefd[0]);
+ write->reset(pipefd[1]);
+ return true;
+}
+
+template <typename Closer>
+inline bool Socketpair(int domain, int type, int protocol, unique_fd_impl<Closer>* left,
+ unique_fd_impl<Closer>* right) {
+ int sockfd[2];
+ if (socketpair(domain, type, protocol, sockfd) != 0) {
+ return false;
+ }
+ left->reset(sockfd[0]);
+ right->reset(sockfd[1]);
+ return true;
+}
+
+template <typename Closer>
+inline bool Socketpair(int type, unique_fd_impl<Closer>* left, unique_fd_impl<Closer>* right) {
+ return Socketpair(AF_UNIX, type, 0, left, right);
+}
+
+// Using fdopen with unique_fd correctly is more annoying than it should be,
+// because fdopen doesn't close the file descriptor received upon failure.
+inline FILE* Fdopen(unique_fd&& ufd, const char* mode) {
+ int fd = ufd.release();
+ FILE* file = fdopen(fd, mode);
+ if (!file) {
+ close(fd);
+ }
+ return file;
+}
+
+// Using fdopendir with unique_fd correctly is more annoying than it should be,
+// because fdopen doesn't close the file descriptor received upon failure.
+inline DIR* Fdopendir(unique_fd&& ufd) {
+ int fd = ufd.release();
+ DIR* dir = fdopendir(fd);
+ if (dir == nullptr) {
+ close(fd);
+ }
+ return dir;
+}
+
+#endif // !defined(_WIN32)
+
+} // namespace base
+} // namespace android
+
+template <typename T>
+int close(const android::base::unique_fd_impl<T>&)
+ __attribute__((__unavailable__("close called on unique_fd")));
+
+template <typename T>
+FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode)
+ __attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the "
+ "unique_fd, or use android::base::Fdopen to pass ownership")));
+
+template <typename T>
+DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__((
+ __unavailable__("fdopendir takes ownership of the fd passed in; either dup the "
+ "unique_fd, or use android::base::Fdopendir to pass ownership")));
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android-base/utf8.h
^
|
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifdef _WIN32
+#include <sys/types.h>
+#include <string>
+#else
+// Bring in prototypes for standard APIs so that we can import them into the utf8 namespace.
+#include <fcntl.h> // open
+#include <stdio.h> // fopen
+#include <sys/stat.h> // mkdir
+#include <unistd.h> // unlink
+#endif
+
+namespace android {
+namespace base {
+
+// Only available on Windows because this is only needed on Windows.
+#ifdef _WIN32
+// Convert size number of UTF-16 wchar_t's to UTF-8. Returns whether the
+// conversion was done successfully.
+bool WideToUTF8(const wchar_t* utf16, const size_t size, std::string* utf8);
+
+// Convert a NULL-terminated string of UTF-16 characters to UTF-8. Returns
+// whether the conversion was done successfully.
+bool WideToUTF8(const wchar_t* utf16, std::string* utf8);
+
+// Convert a UTF-16 std::wstring (including any embedded NULL characters) to
+// UTF-8. Returns whether the conversion was done successfully.
+bool WideToUTF8(const std::wstring& utf16, std::string* utf8);
+
+// Convert size number of UTF-8 char's to UTF-16. Returns whether the conversion
+// was done successfully.
+bool UTF8ToWide(const char* utf8, const size_t size, std::wstring* utf16);
+
+// Convert a NULL-terminated string of UTF-8 characters to UTF-16. Returns
+// whether the conversion was done successfully.
+bool UTF8ToWide(const char* utf8, std::wstring* utf16);
+
+// Convert a UTF-8 std::string (including any embedded NULL characters) to
+// UTF-16. Returns whether the conversion was done successfully.
+bool UTF8ToWide(const std::string& utf8, std::wstring* utf16);
+
+// Convert a file system path, represented as a NULL-terminated string of
+// UTF-8 characters, to a UTF-16 string representing the same file system
+// path using the Windows extended-lengh path representation.
+//
+// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#MAXPATH:
+// ```The Windows API has many functions that also have Unicode versions to
+// permit an extended-length path for a maximum total path length of 32,767
+// characters. To specify an extended-length path, use the "\\?\" prefix.
+// For example, "\\?\D:\very long path".```
+//
+// Returns whether the conversion was done successfully.
+bool UTF8PathToWindowsLongPath(const char* utf8, std::wstring* utf16);
+#endif
+
+// The functions in the utf8 namespace take UTF-8 strings. For Windows, these
+// are wrappers, for non-Windows these just expose existing APIs. To call these
+// functions, use:
+//
+// // anonymous namespace to avoid conflict with existing open(), unlink(), etc.
+// namespace {
+// // Import functions into anonymous namespace.
+// using namespace android::base::utf8;
+//
+// void SomeFunction(const char* name) {
+// int fd = open(name, ...); // Calls android::base::utf8::open().
+// ...
+// unlink(name); // Calls android::base::utf8::unlink().
+// }
+// }
+namespace utf8 {
+
+#ifdef _WIN32
+FILE* fopen(const char* name, const char* mode);
+int mkdir(const char* name, mode_t mode);
+int open(const char* name, int flags, ...);
+int unlink(const char* name);
+#else
+using ::fopen;
+using ::mkdir;
+using ::open;
+using ::unlink;
+#endif
+
+} // namespace utf8
+} // namespace base
+} // namespace android
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android/api-level.h
^
|
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+/**
+ * @file android/api-level.h
+ * @brief Functions and constants for dealing with multiple API levels.
+ */
+
+#include <sys/cdefs-android.h>
+#include <android/versioning.h>
+
+__BEGIN_DECLS
+
+#ifndef __ANDROID_API_FUTURE__
+/**
+ * Magic version number for an Android OS build which has
+ * not yet turned into an official release,
+ * for comparisons against __ANDROID_API__.
+ */
+#define __ANDROID_API_FUTURE__ 10000
+#endif
+
+#ifndef __ANDROID_API__
+/**
+ * `__ANDROID_API__` is the API level being targeted. For the OS,
+ * this is `__ANDROID_API_FUTURE__`. For the NDK, this is set by the
+ * compiler/build system based on the API level you claimed to target.
+ */
+#define __ANDROID_API__ __ANDROID_API_FUTURE__
+#endif
+
+/** Names the Gingerbread API level (9), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_G__ 9
+
+/** Names the Ice-Cream Sandwich API level (14), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_I__ 14
+
+/** Names the Jellybean API level (16), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_J__ 16
+
+/** Names the Jellybean MR1 API level (17), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_J_MR1__ 17
+
+/** Names the Jellybean MR2 API level (18), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_J_MR2__ 18
+
+/** Names the KitKat API level (19), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_K__ 19
+
+/** Names the Lollipop API level (21), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_L__ 21
+
+/** Names the Lollipop MR1 API level (22), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_L_MR1__ 22
+
+/** Names the Marshmallow API level (23), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_M__ 23
+
+/** Names the Nougat API level (24), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_N__ 24
+
+/** Names the Nougat MR1 API level (25), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_N_MR1__ 25
+
+/** Names the Oreo API level (26), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_O__ 26
+
+/** Names the Oreo MR1 API level (27), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_O_MR1__ 27
+
+/** Names the Pie API level (28), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_P__ 28
+
+/** Names the "Q" API level (29), for comparisons against __ANDROID_API__. */
+#define __ANDROID_API_Q__ 29
+
+/**
+ * Returns the `targetSdkVersion` of the caller, or `__ANDROID_API_FUTURE__`
+ * if there is no known target SDK version (for code not running in the
+ * context of an app).
+ *
+ * The returned values correspond to the named constants in `<android/api-level.h>`,
+ * and is equivalent to the AndroidManifest.xml `targetSdkVersion`.
+ *
+ * See also android_get_device_api_level().
+ *
+ * Available since API level 24.
+ */
+int android_get_application_target_sdk_version() __INTRODUCED_IN(24);
+
+#if __ANDROID_API__ < __ANDROID_API_Q__
+
+// android_get_device_api_level is a static inline before API level 29.
+#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
+#include <bits/get_device_api_level_inlines.h>
+#undef __BIONIC_GET_DEVICE_API_LEVEL_INLINE
+
+#else
+
+/**
+ * Returns the API level of the device we're actually running on, or -1 on failure.
+ * The returned values correspond to the named constants in `<android/api-level.h>`,
+ * and is equivalent to the Java `Build.VERSION.SDK_INT` API.
+ *
+ * See also android_get_application_target_sdk_version().
+ */
+int android_get_device_api_level() __INTRODUCED_IN(29);
+
+#endif
+
+__END_DECLS
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android/dlext.h
^
|
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_DLEXT_H__
+#define __ANDROID_DLEXT_H__
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h> /* for off64_t */
+#include <android/versioning.h>
+
+/**
+ * @addtogroup libdl Dynamic Linker
+ * @{
+ */
+
+/**
+ * \file
+ * Advanced dynamic library opening support. Most users will want to use
+ * the standard [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html)
+ * functionality in `<dlfcn.h>` instead.
+ */
+
+__BEGIN_DECLS
+
+/** Bitfield definitions for `android_dlextinfo::flags`. */
+enum {
+ /**
+ * When set, the `reserved_addr` and `reserved_size` fields must point to an
+ * already-reserved region of address space which will be used to load the
+ * library if it fits.
+ *
+ * If the reserved region is not large enough, loading will fail.
+ */
+ ANDROID_DLEXT_RESERVED_ADDRESS = 0x1,
+
+ /**
+ * Like `ANDROID_DLEXT_RESERVED_ADDRESS`, but if the reserved region is not large enough,
+ * the linker will choose an available address instead.
+ */
+ ANDROID_DLEXT_RESERVED_ADDRESS_HINT = 0x2,
+
+ /**
+ * When set, write the GNU RELRO section of the mapped library to `relro_fd`
+ * after relocation has been performed, to allow it to be reused by another
+ * process loading the same library at the same address. This implies
+ * `ANDROID_DLEXT_USE_RELRO`.
+ *
+ * This is mainly useful for the system WebView implementation.
+ */
+ ANDROID_DLEXT_WRITE_RELRO = 0x4,
+
+ /**
+ * When set, compare the GNU RELRO section of the mapped library to `relro_fd`
+ * after relocation has been performed, and replace any relocated pages that
+ * are identical with a version mapped from the file.
+ *
+ * This is mainly useful for the system WebView implementation.
+ */
+ ANDROID_DLEXT_USE_RELRO = 0x8,
+
+ /**
+ * Use `library_fd` instead of opening the file by name.
+ * The filename parameter is still used to identify the library.
+ */
+ ANDROID_DLEXT_USE_LIBRARY_FD = 0x10,
+
+ /**
+ * If opening a library using `library_fd` read it starting at `library_fd_offset`.
+ * This is mainly useful for loading a library stored within another file (such as uncompressed
+ * inside a ZIP archive).
+ * This flag is only valid when `ANDROID_DLEXT_USE_LIBRARY_FD` is set.
+ */
+ ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET = 0x20,
+
+ /**
+ * When set, do not use `stat(2)` to check if the library has already been loaded.
+ *
+ * This flag allows forced loading of the library in the case when for some
+ * reason multiple ELF files share the same filename (because the already-loaded
+ * library has been removed and overwritten, for example).
+ *
+ * Note that if the library has the same `DT_SONAME` as an old one and some other
+ * library has the soname in its `DT_NEEDED` list, the first one will be used to resolve any
+ * dependencies.
+ */
+ ANDROID_DLEXT_FORCE_LOAD = 0x40,
+
+ // Historically we had two other options for ART.
+ // They were last available in Android P.
+ // Reuse these bits last!
+ // ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80
+ // ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100
+
+ /**
+ * This flag used to load library in a different namespace. The namespace is
+ * specified in `library_namespace`.
+ *
+ * This flag is for internal use only (since there is no NDK API for namespaces).
+ */
+ ANDROID_DLEXT_USE_NAMESPACE = 0x200,
+
+ /**
+ * Instructs dlopen to apply `ANDROID_DLEXT_RESERVED_ADDRESS`,
+ * `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`, `ANDROID_DLEXT_WRITE_RELRO` and
+ * `ANDROID_DLEXT_USE_RELRO` to any libraries loaded as dependencies of the
+ * main library as well.
+ *
+ * This means that if the main library depends on one or more not-already-loaded libraries, they
+ * will be loaded consecutively into the region starting at `reserved_addr`, and `reserved_size`
+ * must be large enough to contain all of the libraries. The libraries will be loaded in the
+ * deterministic order constructed from the DT_NEEDED entries, rather than the more secure random
+ * order used by default.
+ *
+ * Each library's GNU RELRO sections will be written out to `relro_fd` in the same order they were
+ * loaded. This will mean that the resulting file is dependent on which of the libraries were
+ * already loaded, as only the newly loaded libraries will be included, not any already-loaded
+ * dependencies. The caller should ensure that the set of libraries newly loaded is consistent
+ * for this to be effective.
+ *
+ * This is mainly useful for the system WebView implementation.
+ */
+ ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE = 0x400,
+
+
+ /** Mask of valid bits. */
+ ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
+ ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
+ ANDROID_DLEXT_WRITE_RELRO |
+ ANDROID_DLEXT_USE_RELRO |
+ ANDROID_DLEXT_USE_LIBRARY_FD |
+ ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
+ ANDROID_DLEXT_FORCE_LOAD |
+ ANDROID_DLEXT_USE_NAMESPACE |
+ ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE,
+};
+
+struct android_namespace_t;
+
+/** Used to pass Android-specific arguments to `android_dlopen_ext`. */
+typedef struct {
+ /** A bitmask of `ANDROID_DLEXT_` enum values. */
+ uint64_t flags;
+
+ /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */
+ void* reserved_addr;
+ /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */
+ size_t reserved_size;
+
+ /** Used by `ANDROID_DLEXT_WRITE_RELRO` and `ANDROID_DLEXT_USE_RELRO`. */
+ int relro_fd;
+
+ /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD`. */
+ int library_fd;
+ /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET` */
+ off64_t library_fd_offset;
+
+ /** Used by `ANDROID_DLEXT_USE_NAMESPACE`. */
+ struct android_namespace_t* library_namespace;
+} android_dlextinfo;
+
+/**
+ * Opens the given library. The `__filename` and `__flags` arguments are
+ * the same as for [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html),
+ * with the Android-specific flags supplied via the `flags` member of `__info`.
+ *
+ * Available since API level 21.
+ */
+void* android_dlopen_ext(const char* __filename, int __flags, const android_dlextinfo* __info)
+ __INTRODUCED_IN(21);
+
+__END_DECLS
+
+/** @} */
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android/fdsan.h
^
|
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/*
+ * Error checking for close(2).
+ *
+ * Mishandling of file descriptor ownership is a common source of errors that
+ * can be extremely difficult to diagnose. Mistakes like the following can
+ * result in seemingly 'impossible' failures showing up on other threads that
+ * happened to try to open a file descriptor between the buggy code's close and
+ * fclose:
+ *
+ * int print(int fd) {
+ * int rc;
+ * char buf[128];
+ * while ((rc = read(fd, buf, sizeof(buf))) > 0) {
+ * printf("%.*s", rc);
+ * }
+ * close(fd);
+ * }
+ *
+ * int bug() {
+ * FILE* f = fopen("foo", "r");
+ * print(fileno(f));
+ * fclose(f);
+ * }
+ *
+ * To make it easier to find this class of bugs, bionic provides a method to
+ * require that file descriptors are closed by their owners. File descriptors
+ * can be associated with tags with which they must be closed. This allows
+ * objects that conceptually own an fd (FILE*, unique_fd, etc.) to use their
+ * own address at the tag, to enforce that closure of the fd must come as a
+ * result of their own destruction (fclose, ~unique_fd, etc.)
+ *
+ * By default, a file descriptor's tag is 0, and close(fd) is equivalent to
+ * closing fd with the tag 0.
+ */
+
+/*
+ * For improved diagnostics, the type of a file descriptors owner can be
+ * encoded in the most significant byte of the owner tag. Values of 0 and 0xff
+ * are ignored, which allows for raw pointers to be used as owner tags without
+ * modification.
+ */
+enum android_fdsan_owner_type {
+ /*
+ * Generic Java or native owners.
+ *
+ * Generic Java objects always use 255 as their type, using identityHashCode
+ * as the value of the tag, leaving bits 33-56 unset. Native pointers are sign
+ * extended from 48-bits of virtual address space, and so can have the MSB
+ * set to 255 as well. Use the value of bits 49-56 to distinguish between
+ * these cases.
+ */
+ ANDROID_FDSAN_OWNER_TYPE_GENERIC_00 = 0,
+ ANDROID_FDSAN_OWNER_TYPE_GENERIC_FF = 255,
+
+ /* FILE* */
+ ANDROID_FDSAN_OWNER_TYPE_FILE = 1,
+
+ /* DIR* */
+ ANDROID_FDSAN_OWNER_TYPE_DIR = 2,
+
+ /* android::base::unique_fd */
+ ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD = 3,
+
+ /* sqlite-owned file descriptors */
+ ANDROID_FDSAN_OWNER_TYPE_SQLITE = 4,
+
+ /* java.io.FileInputStream */
+ ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 5,
+
+ /* java.io.FileOutputStream */
+ ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 6,
+
+ /* java.io.RandomAccessFile */
+ ANDROID_FDSAN_OWNER_TYPE_RANDOMACCESSFILE = 7,
+
+ /* android.os.ParcelFileDescriptor */
+ ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 8,
+
+ /* ART FdFile */
+ ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE = 9,
+
+ /* java.net.DatagramSocketImpl */
+ ANDROID_FDSAN_OWNER_TYPE_DATAGRAMSOCKETIMPL = 10,
+
+ /* java.net.SocketImpl */
+ ANDROID_FDSAN_OWNER_TYPE_SOCKETIMPL = 11,
+
+ /* libziparchive's ZipArchive */
+ ANDROID_FDSAN_OWNER_TYPE_ZIPARCHIVE = 12,
+};
+
+/*
+ * Create an owner tag with the specified type and least significant 56 bits of tag.
+ */
+uint64_t android_fdsan_create_owner_tag(enum android_fdsan_owner_type type, uint64_t tag) __INTRODUCED_IN(29) __attribute__((__weak__));
+
+/*
+ * Exchange a file descriptor's tag.
+ *
+ * Logs and aborts if the fd's tag does not match expected_tag.
+ */
+void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t new_tag) __INTRODUCED_IN(29) __attribute__((__weak__));
+
+/*
+ * Close a file descriptor with a tag, and resets the tag to 0.
+ *
+ * Logs and aborts if the tag is incorrect.
+ */
+int android_fdsan_close_with_tag(int fd, uint64_t tag) __INTRODUCED_IN(29) __attribute__((__weak__));
+
+/*
+ * Get a file descriptor's current owner tag.
+ *
+ * Returns 0 for untagged and invalid file descriptors.
+ */
+uint64_t android_fdsan_get_owner_tag(int fd) __INTRODUCED_IN(29);
+
+/*
+ * Get an owner tag's string representation.
+ *
+ * The return value points to memory with static lifetime, do not attempt to modify it.
+ */
+const char* android_fdsan_get_tag_type(uint64_t tag) __INTRODUCED_IN(29);
+
+/*
+ * Get an owner tag's value, with the type masked off.
+ */
+uint64_t android_fdsan_get_tag_value(uint64_t tag) __INTRODUCED_IN(29);
+
+enum android_fdsan_error_level {
+ // No errors.
+ ANDROID_FDSAN_ERROR_LEVEL_DISABLED,
+
+ // Warn once(ish) on error, and then downgrade to ANDROID_FDSAN_ERROR_LEVEL_DISABLED.
+ ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE,
+
+ // Warn always on error.
+ ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS,
+
+ // Abort on error.
+ ANDROID_FDSAN_ERROR_LEVEL_FATAL,
+};
+
+/*
+ * Get the error level.
+ */
+enum android_fdsan_error_level android_fdsan_get_error_level() __INTRODUCED_IN(29) __attribute__((__weak__));
+
+/*
+ * Set the error level and return the previous state.
+ *
+ * Error checking is automatically disabled in the child of a fork, to maintain
+ * compatibility with code that forks, blindly closes FDs, and then execs.
+ *
+ * In cases such as the zygote, where the child has no intention of calling
+ * exec, call this function to reenable fdsan checks.
+ *
+ * This function is not thread-safe and does not synchronize with checks of the
+ * value, and so should probably only be called in single-threaded contexts
+ * (e.g. postfork).
+ */
+enum android_fdsan_error_level android_fdsan_set_error_level(enum android_fdsan_error_level new_level) __INTRODUCED_IN(29) __attribute__((__weak__));
+
+__END_DECLS
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/android/versioning.h
^
|
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" #api_level)))
+#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" #api_level)))
+#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level)))
+#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level)))
+#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level)))
+#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level)))
+#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level)))
+#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" #api_level)))
+
+#define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard")))
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/dlfcn.h
^
|
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __DLFCN_H__
+#define __DLFCN_H__
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <android/versioning.h>
+__BEGIN_DECLS
+
+#if defined(__cplusplus)
+#define __BIONIC_CAST(_k,_t,_v) (_k<_t>(_v))
+#else
+#define __BIONIC_CAST(_k,_t,_v) ((_t) (_v))
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnullability-completeness"
+#endif
+
+typedef struct {
+ /* Pathname of shared object that contains address. */
+ const char* dli_fname;
+ /* Address at which shared object is loaded. */
+ void* dli_fbase;
+ /* Name of nearest symbol with address lower than addr. */
+ const char* dli_sname;
+ /* Exact address of symbol named in dli_sname. */
+ void* dli_saddr;
+} Dl_info;
+
+void* dlopen(const char* __filename, int __flag);
+int dlclose(void* __handle);
+char* dlerror(void);
+void* dlsym(void* __handle, const char* __symbol);
+void* dlvsym(void* __handle, const char* __symbol, const char* __version) __INTRODUCED_IN(24);
+int dladdr(const void* __addr, Dl_info* __info);
+
+#define RTLD_LOCAL 0
+#define RTLD_LAZY 0x00001
+#define RTLD_NOW 0x00002
+#define RTLD_NOLOAD 0x00004
+#define RTLD_GLOBAL 0x00100
+#define RTLD_NODELETE 0x01000
+
+#if !defined(__LP64__)
+/* LP32 is broken for historical reasons. */
+#undef RTLD_NOW
+#define RTLD_NOW 0x00000
+#undef RTLD_GLOBAL
+#define RTLD_GLOBAL 0x00002
+#endif
+
+#if defined (__LP64__)
+#define RTLD_DEFAULT __BIONIC_CAST(reinterpret_cast, void*, 0)
+#define RTLD_NEXT __BIONIC_CAST(reinterpret_cast, void*, -1L)
+#else
+#define RTLD_DEFAULT __BIONIC_CAST(reinterpret_cast, void*, 0xffffffff)
+#define RTLD_NEXT __BIONIC_CAST(reinterpret_cast, void*, 0xfffffffe)
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+__END_DECLS
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/link.h
^
|
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _LINK_H_
+#define _LINK_H_
+
+#include <android/versioning.h> // for __INTRODUCED_IN
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <elf.h>
+
+__BEGIN_DECLS
+
+typedef Elf32_Word Elf32_Relr;
+typedef Elf64_Xword Elf64_Relr;
+
+#if defined(__LP64__)
+#define ElfW(type) Elf64_ ## type
+#else
+#define ElfW(type) Elf32_ ## type
+#endif
+
+struct dl_phdr_info {
+ ElfW(Addr) dlpi_addr;
+ const char* dlpi_name;
+ const ElfW(Phdr)* dlpi_phdr;
+ ElfW(Half) dlpi_phnum;
+};
+
+#if defined(__arm__)
+int dl_iterate_phdr(int (*__callback)(struct dl_phdr_info*, size_t, void*), void* __data) __INTRODUCED_IN(21);
+#else
+int dl_iterate_phdr(int (*__callback)(struct dl_phdr_info*, size_t, void*), void* __data);
+#endif
+
+#ifdef __arm__
+typedef uintptr_t _Unwind_Ptr;
+_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr, int*);
+#endif
+
+/* Used by the dynamic linker to communicate with the debugger. */
+struct link_map {
+ ElfW(Addr) l_addr;
+ char* l_name;
+ ElfW(Dyn)* l_ld;
+ struct link_map* l_next;
+ struct link_map* l_prev;
+};
+
+/* Used by the dynamic linker to communicate with the debugger. */
+struct r_debug {
+ int32_t r_version;
+ struct link_map* r_map;
+ ElfW(Addr) r_brk;
+ enum {
+ RT_CONSISTENT,
+ RT_ADD,
+ RT_DELETE
+ } r_state;
+ ElfW(Addr) r_ldbase;
+};
+
+__END_DECLS
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/stdatomic.h
^
|
@@ -0,0 +1,525 @@
+/*-
+ * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
+ * David Chisnall <theraven@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _STDATOMIC_H_
+#define _STDATOMIC_H_
+
+#include <sys/cdefs.h>
+
+#define XSTR(x) STR(x)
+#define STR(x) #x
+#pragma message "__cplusplus=" XSTR(__cplusplus)
+#pragma message "_USING_LIBCXX=" XSTR(_USING_LIBCXX)
+
+#if defined(__cplusplus) && __cplusplus >= 201103L && defined(_USING_LIBCXX)
+# ifdef __clang__
+# if __has_feature(cxx_atomic)
+# define _STDATOMIC_HAVE_ATOMIC
+# endif
+# else
+# define _STDATOMIC_HAVE_ATOMIC
+# endif
+#endif
+
+#define _STDATOMIC_HAVE_ATOMIC
+#ifdef _STDATOMIC_HAVE_ATOMIC
+
+/* We have a usable C++ <atomic>; use it instead. */
+
+#include <atomic>
+
+#undef _Atomic
+ /* Also defined by <atomic> for gcc. But not used in macros. */
+ /* Also a clang intrinsic. */
+ /* Should not be used by client code before this file is */
+ /* included. The definitions in <atomic> themselves see */
+ /* the old definition, as they should. */
+ /* Client code sees the following definition. */
+
+#define _Atomic(t) std::atomic<t>
+
+using std::atomic_is_lock_free;
+using std::atomic_init;
+using std::atomic_store;
+using std::atomic_store_explicit;
+using std::atomic_load;
+using std::atomic_load_explicit;
+using std::atomic_exchange;
+using std::atomic_exchange_explicit;
+using std::atomic_compare_exchange_strong;
+using std::atomic_compare_exchange_strong_explicit;
+using std::atomic_compare_exchange_weak;
+using std::atomic_compare_exchange_weak_explicit;
+using std::atomic_fetch_add;
+using std::atomic_fetch_add_explicit;
+using std::atomic_fetch_sub;
+using std::atomic_fetch_sub_explicit;
+using std::atomic_fetch_or;
+using std::atomic_fetch_or_explicit;
+using std::atomic_fetch_xor;
+using std::atomic_fetch_xor_explicit;
+using std::atomic_fetch_and;
+using std::atomic_fetch_and_explicit;
+using std::atomic_thread_fence;
+using std::atomic_signal_fence;
+
+using std::memory_order;
+using std::memory_order_relaxed;
+using std::memory_order_consume;
+using std::memory_order_acquire;
+using std::memory_order_release;
+using std::memory_order_acq_rel;
+using std::memory_order_seq_cst;
+
+using std::atomic_bool;
+using std::atomic_char;
+using std::atomic_schar;
+using std::atomic_uchar;
+using std::atomic_short;
+using std::atomic_ushort;
+using std::atomic_int;
+using std::atomic_uint;
+using std::atomic_long;
+using std::atomic_ulong;
+using std::atomic_llong;
+using std::atomic_ullong;
+using std::atomic_char16_t;
+using std::atomic_char32_t;
+using std::atomic_wchar_t;
+using std::atomic_int_least8_t;
+using std::atomic_uint_least8_t;
+using std::atomic_int_least16_t;
+using std::atomic_uint_least16_t;
+using std::atomic_int_least32_t;
+using std::atomic_uint_least32_t;
+using std::atomic_int_least64_t;
+using std::atomic_uint_least64_t;
+using std::atomic_int_fast8_t;
+using std::atomic_uint_fast8_t;
+using std::atomic_int_fast16_t;
+using std::atomic_uint_fast16_t;
+using std::atomic_int_fast32_t;
+using std::atomic_uint_fast32_t;
+using std::atomic_int_fast64_t;
+using std::atomic_uint_fast64_t;
+using std::atomic_intptr_t;
+using std::atomic_uintptr_t;
+using std::atomic_size_t;
+using std::atomic_ptrdiff_t;
+using std::atomic_intmax_t;
+using std::atomic_uintmax_t;
+
+#else /* <atomic> unavailable, possibly because this is C, not C++ */
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+/*
+ * C: Do it ourselves.
+ * Note that the runtime representation defined here should be compatible
+ * with the C++ one, i.e. an _Atomic(T) needs to contain the same
+ * bits as a T.
+ */
+
+#include <stddef.h> /* For ptrdiff_t. */
+#include <stdint.h> /* TODO: don't drag in all the macros, just the types. */
+// Include uchar.h only when available. Bionic's stdatomic.h is also used for
+// the host (via a copy in prebuilts/clang) and uchar.h is not available in the
+// glibc used for the host.
+#if __STDC_VERSION__ >= 201112L
+# include <uchar.h> /* For char16_t and char32_t. */
+#endif
+
+#ifdef __clang__
+# if __has_extension(c_atomic) || __has_extension(cxx_atomic)
+# define __CLANG_ATOMICS
+# else
+# error "stdatomic.h does not support your compiler"
+# endif
+# if __has_builtin(__sync_swap)
+# define __HAS_BUILTIN_SYNC_SWAP
+# endif
+#else
+# define __GNUC_ATOMICS
+#endif
+
+/*
+ * 7.17.1 Atomic lock-free macros.
+ */
+
+#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
+#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
+#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
+#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_INT_LOCK_FREE
+#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_LONG_LOCK_FREE
+#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
+#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
+#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
+#endif
+
+/*
+ * 7.17.2 Initialization.
+ */
+
+#if defined(__CLANG_ATOMICS)
+#define ATOMIC_VAR_INIT(value) (value)
+#define atomic_init(obj, value) __c11_atomic_init(obj, value)
+#else
+#define ATOMIC_VAR_INIT(value) { .__val = (value) }
+#define atomic_init(obj, value) ((void)((obj)->__val = (value)))
+#endif
+
+/*
+ * Clang and recent GCC both provide predefined macros for the memory
+ * orderings. If we are using a compiler that doesn't define them, use the
+ * clang values - these will be ignored in the fallback path.
+ */
+
+#ifndef __ATOMIC_RELAXED
+#define __ATOMIC_RELAXED 0
+#endif
+#ifndef __ATOMIC_CONSUME
+#define __ATOMIC_CONSUME 1
+#endif
+#ifndef __ATOMIC_ACQUIRE
+#define __ATOMIC_ACQUIRE 2
+#endif
+#ifndef __ATOMIC_RELEASE
+#define __ATOMIC_RELEASE 3
+#endif
+#ifndef __ATOMIC_ACQ_REL
+#define __ATOMIC_ACQ_REL 4
+#endif
+#ifndef __ATOMIC_SEQ_CST
+#define __ATOMIC_SEQ_CST 5
+#endif
+
+/*
+ * 7.17.3 Order and consistency.
+ *
+ * The memory_order_* constants that denote the barrier behaviour of the
+ * atomic operations.
+ * The enum values must be identical to those used by the
+ * C++ <atomic> header.
+ */
+
+typedef enum {
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_consume = __ATOMIC_CONSUME,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
+} memory_order;
+
+/*
+ * 7.17.4 Fences.
+ */
+
+static __inline void atomic_thread_fence(memory_order __order __attribute__((unused))) {
+#ifdef __CLANG_ATOMICS
+ __c11_atomic_thread_fence(__order);
+#elif defined(__GNUC_ATOMICS)
+ __atomic_thread_fence(__order);
+#else
+ __sync_synchronize();
+#endif
+}
+
+static __inline void atomic_signal_fence(memory_order __order __attribute__((unused))) {
+#ifdef __CLANG_ATOMICS
+ __c11_atomic_signal_fence(__order);
+#elif defined(__GNUC_ATOMICS)
+ __atomic_signal_fence(__order);
+#else
+ __asm volatile ("" ::: "memory");
+#endif
+}
+
+/*
+ * 7.17.5 Lock-free property.
+ */
+
+#if defined(_KERNEL)
+/* Atomics in kernelspace are always lock-free. */
+#define atomic_is_lock_free(obj) \
+ ((void)(obj), (_Bool)1)
+#elif defined(__CLANG_ATOMICS)
+#define atomic_is_lock_free(obj) \
+ __c11_atomic_is_lock_free(sizeof(*(obj)))
+#elif defined(__GNUC_ATOMICS)
+#define atomic_is_lock_free(obj) \
+ __atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
+#else
+#define atomic_is_lock_free(obj) \
+ ((void)(obj), sizeof((obj)->__val) <= sizeof(void *))
+#endif
+
+/*
+ * 7.17.6 Atomic integer types.
+ */
+
+#ifndef __CLANG_ATOMICS
+/*
+ * No native support for _Atomic(). Place object in structure to prevent
+ * most forms of direct non-atomic access.
+ */
+#define _Atomic(T) struct { T volatile __val; }
+#endif
+
+typedef _Atomic(bool) atomic_bool;
+typedef _Atomic(char) atomic_char;
+typedef _Atomic(signed char) atomic_schar;
+typedef _Atomic(unsigned char) atomic_uchar;
+typedef _Atomic(short) atomic_short;
+typedef _Atomic(unsigned short) atomic_ushort;
+typedef _Atomic(int) atomic_int;
+typedef _Atomic(unsigned int) atomic_uint;
+typedef _Atomic(long) atomic_long;
+typedef _Atomic(unsigned long) atomic_ulong;
+typedef _Atomic(long long) atomic_llong;
+typedef _Atomic(unsigned long long) atomic_ullong;
+#if __STDC_VERSION__ >= 201112L || (defined(__cplusplus) && __cplusplus >= 201103L)
+ typedef _Atomic(char16_t) atomic_char16_t;
+ typedef _Atomic(char32_t) atomic_char32_t;
+#endif
+typedef _Atomic(wchar_t) atomic_wchar_t;
+typedef _Atomic(int_least8_t) atomic_int_least8_t;
+typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
+typedef _Atomic(int_least16_t) atomic_int_least16_t;
+typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
+typedef _Atomic(int_least32_t) atomic_int_least32_t;
+typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
+typedef _Atomic(int_least64_t) atomic_int_least64_t;
+typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
+typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
+typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
+typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
+typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
+typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
+typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
+typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
+typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
+typedef _Atomic(intptr_t) atomic_intptr_t;
+typedef _Atomic(uintptr_t) atomic_uintptr_t;
+typedef _Atomic(size_t) atomic_size_t;
+typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
+typedef _Atomic(intmax_t) atomic_intmax_t;
+typedef _Atomic(uintmax_t) atomic_uintmax_t;
+
+/*
+ * 7.17.7 Operations on atomic types.
+ */
+
+/*
+ * Compiler-specific operations.
+ */
+
+#if defined(__CLANG_ATOMICS)
+#define atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, success, failure) \
+ __c11_atomic_compare_exchange_strong(object, expected, desired, \
+ success, failure)
+#define atomic_compare_exchange_weak_explicit(object, expected, \
+ desired, success, failure) \
+ __c11_atomic_compare_exchange_weak(object, expected, desired, \
+ success, failure)
+#define atomic_exchange_explicit(object, desired, order) \
+ __c11_atomic_exchange(object, desired, order)
+#define atomic_fetch_add_explicit(object, operand, order) \
+ __c11_atomic_fetch_add(object, operand, order)
+#define atomic_fetch_and_explicit(object, operand, order) \
+ __c11_atomic_fetch_and(object, operand, order)
+#define atomic_fetch_or_explicit(object, operand, order) \
+ __c11_atomic_fetch_or(object, operand, order)
+#define atomic_fetch_sub_explicit(object, operand, order) \
+ __c11_atomic_fetch_sub(object, operand, order)
+#define atomic_fetch_xor_explicit(object, operand, order) \
+ __c11_atomic_fetch_xor(object, operand, order)
+#define atomic_load_explicit(object, order) \
+ __c11_atomic_load(object, order)
+#define atomic_store_explicit(object, desired, order) \
+ __c11_atomic_store(object, desired, order)
+#elif defined(__GNUC_ATOMICS)
+#define atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, success, failure) \
+ __atomic_compare_exchange_n(&(object)->__val, expected, \
+ desired, 0, success, failure)
+#define atomic_compare_exchange_weak_explicit(object, expected, \
+ desired, success, failure) \
+ __atomic_compare_exchange_n(&(object)->__val, expected, \
+ desired, 1, success, failure)
+#define atomic_exchange_explicit(object, desired, order) \
+ __atomic_exchange_n(&(object)->__val, desired, order)
+#define atomic_fetch_add_explicit(object, operand, order) \
+ __atomic_fetch_add(&(object)->__val, operand, order)
+#define atomic_fetch_and_explicit(object, operand, order) \
+ __atomic_fetch_and(&(object)->__val, operand, order)
+#define atomic_fetch_or_explicit(object, operand, order) \
+ __atomic_fetch_or(&(object)->__val, operand, order)
+#define atomic_fetch_sub_explicit(object, operand, order) \
+ __atomic_fetch_sub(&(object)->__val, operand, order)
+#define atomic_fetch_xor_explicit(object, operand, order) \
+ __atomic_fetch_xor(&(object)->__val, operand, order)
+#define atomic_load_explicit(object, order) \
+ __atomic_load_n(&(object)->__val, order)
+#define atomic_store_explicit(object, desired, order) \
+ __atomic_store_n(&(object)->__val, desired, order)
+#else
+#define __atomic_apply_stride(object, operand) \
+ (((__typeof__((object)->__val))0) + (operand))
+#define atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, success, failure) __extension__ ({ \
+ __typeof__(expected) __ep = (expected); \
+ __typeof__(*__ep) __e = *__ep; \
+ (void)(success); (void)(failure); \
+ (bool)((*__ep = __sync_val_compare_and_swap(&(object)->__val, \
+ __e, desired)) == __e); \
+})
+#define atomic_compare_exchange_weak_explicit(object, expected, \
+ desired, success, failure) \
+ atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, success, failure)
+#ifdef __HAS_BUILTIN_SYNC_SWAP
+/* Clang provides a full-barrier atomic exchange - use it if available. */
+#define atomic_exchange_explicit(object, desired, order) \
+ ((void)(order), __sync_swap(&(object)->__val, desired))
+#else
+/*
+ * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
+ * practice it is usually a full barrier) so we need an explicit barrier before
+ * it.
+ */
+#define atomic_exchange_explicit(object, desired, order) \
+__extension__ ({ \
+ __typeof__(object) __o = (object); \
+ __typeof__(desired) __d = (desired); \
+ (void)(order); \
+ __sync_synchronize(); \
+ __sync_lock_test_and_set(&(__o)->__val, __d); \
+})
+#endif
+#define atomic_fetch_add_explicit(object, operand, order) \
+ ((void)(order), __sync_fetch_and_add(&(object)->__val, \
+ __atomic_apply_stride(object, operand)))
+#define atomic_fetch_and_explicit(object, operand, order) \
+ ((void)(order), __sync_fetch_and_and(&(object)->__val, operand))
+#define atomic_fetch_or_explicit(object, operand, order) \
+ ((void)(order), __sync_fetch_and_or(&(object)->__val, operand))
+#define atomic_fetch_sub_explicit(object, operand, order) \
+ ((void)(order), __sync_fetch_and_sub(&(object)->__val, \
+ __atomic_apply_stride(object, operand)))
+#define atomic_fetch_xor_explicit(object, operand, order) \
+ ((void)(order), __sync_fetch_and_xor(&(object)->__val, operand))
+#define atomic_load_explicit(object, order) \
+ ((void)(order), __sync_fetch_and_add(&(object)->__val, 0))
+#define atomic_store_explicit(object, desired, order) \
+ ((void)atomic_exchange_explicit(object, desired, order))
+#endif
+
+/*
+ * Convenience functions.
+ */
+
+#define atomic_compare_exchange_strong(object, expected, desired) \
+ atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, memory_order_seq_cst, memory_order_seq_cst)
+#define atomic_compare_exchange_weak(object, expected, desired) \
+ atomic_compare_exchange_weak_explicit(object, expected, \
+ desired, memory_order_seq_cst, memory_order_seq_cst)
+#define atomic_exchange(object, desired) \
+ atomic_exchange_explicit(object, desired, memory_order_seq_cst)
+#define atomic_fetch_add(object, operand) \
+ atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_and(object, operand) \
+ atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_or(object, operand) \
+ atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_sub(object, operand) \
+ atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_xor(object, operand) \
+ atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
+#define atomic_load(object) \
+ atomic_load_explicit(object, memory_order_seq_cst)
+#define atomic_store(object, desired) \
+ atomic_store_explicit(object, desired, memory_order_seq_cst)
+
+/*
+ * 7.17.8 Atomic flag type and operations.
+ *
+ * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
+ * kind of compiler built-in type we could use?
+ */
+
+typedef struct {
+ atomic_bool __flag;
+} atomic_flag;
+
+#define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(false) }
+
+static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag *__object, memory_order __order) {
+ return (atomic_exchange_explicit(&__object->__flag, 1, __order));
+}
+
+static __inline void atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order) {
+ atomic_store_explicit(&__object->__flag, 0, __order);
+}
+
+static __inline bool atomic_flag_test_and_set(volatile atomic_flag *__object) {
+ return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst));
+}
+
+static __inline void atomic_flag_clear(volatile atomic_flag *__object) {
+ atomic_flag_clear_explicit(__object, memory_order_seq_cst);
+}
+
+#endif /* <atomic> unavailable */
+
+#endif /* !_STDATOMIC_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/sys/_system_properties.h
^
|
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _INCLUDE_SYS__SYSTEM_PROPERTIES_H
+#define _INCLUDE_SYS__SYSTEM_PROPERTIES_H
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+#ifndef _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#error you should #include <sys/system_properties.h> instead
+#endif
+
+#include <sys/system_properties.h>
+
+__BEGIN_DECLS
+
+#define PROP_SERVICE_NAME "property_service"
+#define PROP_FILENAME "/dev/__properties__"
+
+#define PROP_MSG_SETPROP 1
+#define PROP_MSG_SETPROP2 0x00020001
+
+#define PROP_SUCCESS 0
+#define PROP_ERROR_READ_CMD 0x0004
+#define PROP_ERROR_READ_DATA 0x0008
+#define PROP_ERROR_READ_ONLY_PROPERTY 0x000B
+#define PROP_ERROR_INVALID_NAME 0x0010
+#define PROP_ERROR_INVALID_VALUE 0x0014
+#define PROP_ERROR_PERMISSION_DENIED 0x0018
+#define PROP_ERROR_INVALID_CMD 0x001B
+#define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
+#define PROP_ERROR_SET_FAILED 0x0024
+
+/*
+** This was previously for testing, but now that SystemProperties is its own testable class,
+** there is never a reason to call this function and its implementation simply returns -1.
+*/
+int __system_property_set_filename(const char* __filename);
+
+/*
+** Initialize the area to be used to store properties. Can
+** only be done by a single process that has write access to
+** the property area.
+*/
+int __system_property_area_init(void);
+
+/* Read the global serial number of the system properties
+**
+** Called to predict if a series of cached __system_property_find
+** objects will have seen __system_property_serial values change.
+** But also aids the converse, as changes in the global serial can
+** also be used to predict if a failed __system_property_find
+** could in-turn now find a new object; thus preventing the
+** cycles of effort to poll __system_property_find.
+**
+** Typically called at beginning of a cache cycle to signal if _any_ possible
+** changes have occurred since last. If there is, one may check each individual
+** __system_property_serial to confirm dirty, or __system_property_find
+** to check if the property now exists. If a call to __system_property_add
+** or __system_property_update has completed between two calls to
+** __system_property_area_serial then the second call will return a larger
+** value than the first call. Beware of race conditions as changes to the
+** properties are not atomic, the main value of this call is to determine
+** whether the expensive __system_property_find is worth retrying to see if
+** a property now exists.
+**
+** Returns the serial number on success, -1 on error.
+*/
+uint32_t __system_property_area_serial(void);
+
+/* Add a new system property. Can only be done by a single
+** process that has write access to the property area, and
+** that process must handle sequencing to ensure the property
+** does not already exist and that only one property is added
+** or updated at a time.
+**
+** Returns 0 on success, -1 if the property area is full.
+*/
+int __system_property_add(const char* __name, unsigned int __name_length, const char* __value, unsigned int __value_length);
+
+/* Update the value of a system property returned by
+** __system_property_find. Can only be done by a single process
+** that has write access to the property area, and that process
+** must handle sequencing to ensure that only one property is
+** updated at a time.
+**
+** Returns 0 on success, -1 if the parameters are incorrect.
+*/
+int __system_property_update(prop_info* __pi, const char* __value, unsigned int __value_length);
+
+/* Read the serial number of a system property returned by
+** __system_property_find.
+**
+** Returns the serial number on success, -1 on error.
+*/
+uint32_t __system_property_serial(const prop_info* __pi);
+
+/* Initialize the system properties area in read only mode.
+ * Should be done by all processes that need to read system
+ * properties.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int __system_properties_init(void);
+
+/* Deprecated: use __system_property_wait instead. */
+uint32_t __system_property_wait_any(uint32_t __old_serial);
+
+__END_DECLS
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/sys/cdefs-android.h
^
|
@@ -0,0 +1,5 @@
+#pragma once
+#include <sys/cdefs.h>
+#define __LIBC_HIDDEN__ __attribute__((visibility("hidden")))
+#define __unused __attribute__((__unused__))
+#define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1))
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/include/sys/system_properties.h
^
|
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _INCLUDE_SYS_SYSTEM_PROPERTIES_H
+#define _INCLUDE_SYS_SYSTEM_PROPERTIES_H
+
+#include <sys/cdefs.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+typedef struct prop_info prop_info;
+
+#define PROP_VALUE_MAX 92
+
+/*
+ * Sets system property `name` to `value`, creating the system property if it doesn't already exist.
+ */
+int __system_property_set(const char* __name, const char* __value) __INTRODUCED_IN(12);
+
+/*
+ * Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist.
+ * Use __system_property_read_callback to query the current value.
+ *
+ * Property lookup is expensive, so it can be useful to cache the result of this function.
+ */
+const prop_info* __system_property_find(const char* __name);
+
+/*
+ * Calls `callback` with a consistent trio of name, value, and serial number for property `pi`.
+ */
+void __system_property_read_callback(const prop_info* __pi,
+ void (*__callback)(void* __cookie, const char* __name, const char* __value, uint32_t __serial),
+ void* __cookie) __INTRODUCED_IN(26);
+
+/*
+ * Passes a `prop_info` for each system property to the provided
+ * callback. Use __system_property_read_callback() to read the value.
+ *
+ * This method is for inspecting and debugging the property system, and not generally useful.
+ */
+int __system_property_foreach(void (*__callback)(const prop_info* __pi, void* __cookie), void* __cookie)
+ __INTRODUCED_IN(19);
+
+/*
+ * Waits for the specific system property identified by `pi` to be updated
+ * past `old_serial`. Waits no longer than `relative_timeout`, or forever
+ * if `relaive_timeout` is null.
+ *
+ * If `pi` is null, waits for the global serial number instead.
+ *
+ * If you don't know the current serial, use 0.
+ *
+ * Returns true and updates `*new_serial_ptr` on success, or false if the call
+ * timed out.
+ */
+struct timespec;
+bool __system_property_wait(const prop_info* __pi, uint32_t __old_serial, uint32_t* __new_serial_ptr, const struct timespec* __relative_timeout)
+ __INTRODUCED_IN(26);
+
+/* Deprecated. In Android O and above, there's no limit on property name length. */
+#define PROP_NAME_MAX 32
+/* Deprecated. Use __system_property_read_callback instead. */
+int __system_property_read(const prop_info* __pi, char* __name, char* __value);
+/* Deprecated. Use __system_property_read_callback instead. */
+int __system_property_get(const char* __name, char* __value);
+/* Deprecated. Use __system_property_foreach instead. */
+const prop_info* __system_property_find_nth(unsigned __n);
+
+__END_DECLS
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/CFIShadow.h
^
|
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CFI_SHADOW_H
+#define CFI_SHADOW_H
+
+#include <stdint.h>
+
+#include "private/bionic_page.h"
+#include "private/bionic_macros.h"
+
+constexpr unsigned kLibraryAlignmentBits = 18;
+constexpr size_t kLibraryAlignment = 1UL << kLibraryAlignmentBits;
+
+// This class defines format of the shadow region for Control Flow Integrity support.
+// See documentation in http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#shared-library-support.
+//
+// CFI shadow is effectively a very fast and specialized implementation of dladdr: given an address that
+// belongs to a shared library or an executable, it can find the address of a specific export in that
+// library (a function called "__cfi_check"). This is only guaranteed to work for
+// addresses of possible CFI targets inside a library: indirectly called functions and virtual
+// tables. A random address inside a library may not work in the future (but it does in the current
+// implementation).
+//
+// Implementation is a sparse array of uint16_t where each element describes the location of
+// __cfi_check for a 2**kShadowGranularity range of memory. Array elements (called "shadow values"
+// below) are interpreted as follows.
+//
+// For an address P and corresponding shadow value V, the address of __cfi_check is calculated as
+// align_up(P, 2**kShadowGranularity) - (V - 2) * (2 ** kCfiCheckGranularity)
+//
+// Special shadow values:
+// 0 = kInvalidShadow, this memory range has no valid CFI targets.
+// 1 = kUncheckedShadow, any address is this memory range is a valid CFI target
+//
+// Loader requirement: each aligned 2**kShadowGranularity region of address space may contain at
+// most one DSO.
+// Compiler requirement: __cfi_check is aligned at kCfiCheckGranularity.
+// Compiler requirement: __cfi_check for a given DSO is located below any CFI target for that DSO.
+class CFIShadow {
+ public:
+ static constexpr uintptr_t kShadowGranularity = kLibraryAlignmentBits;
+ static constexpr uintptr_t kCfiCheckGranularity = 12;
+
+ // Each uint16_t element of the shadow corresponds to this much application memory.
+ static constexpr uintptr_t kShadowAlign = 1UL << kShadowGranularity;
+
+ // Alignment of __cfi_check.
+ static constexpr uintptr_t kCfiCheckAlign = 1UL << kCfiCheckGranularity; // 4K
+
+#if defined (__LP64__)
+ static constexpr uintptr_t kMaxTargetAddr = 0xffffffffffff;
+#else
+ static constexpr uintptr_t kMaxTargetAddr = 0xffffffff;
+#endif
+
+ // Shadow is 2 -> 2**kShadowGranularity.
+ static constexpr uintptr_t kShadowSize =
+ align_up((kMaxTargetAddr >> (kShadowGranularity - 1)), PAGE_SIZE);
+
+ // Returns offset inside the shadow region for an address.
+ static constexpr uintptr_t MemToShadowOffset(uintptr_t x) {
+ return (x >> kShadowGranularity) << 1;
+ }
+
+ typedef int (*CFICheckFn)(uint64_t, void *, void *);
+
+ public:
+ enum ShadowValues : uint16_t {
+ kInvalidShadow = 0, // Not a valid CFI target.
+ kUncheckedShadow = 1, // Unchecked, valid CFI target.
+ kRegularShadowMin = 2 // This and all higher values encode a negative offset to __cfi_check in
+ // the units of kCfiCheckGranularity, starting with 0 at
+ // kRegularShadowMin.
+ };
+};
+
+#endif // CFI_SHADOW_H
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/CachedProperty.h
^
|
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <string.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+// Cached system property lookup. For code that needs to read the same property multiple times,
+// this class helps optimize those lookups.
+class CachedProperty {
+ public:
+ // The lifetime of `property_name` must be greater than that of this CachedProperty.
+ explicit CachedProperty(const char* property_name)
+ : property_name_(property_name),
+ prop_info_(nullptr),
+ cached_area_serial_(0),
+ cached_property_serial_(0),
+ is_read_only_(strncmp(property_name, "ro.", 3) == 0),
+ read_only_property_(nullptr) {
+ cached_value_[0] = '\0';
+ }
+
+ // Returns true if the property has been updated (based on the serial rather than the value)
+ // since the last call to Get.
+ bool DidChange() {
+ uint32_t initial_property_serial_ = cached_property_serial_;
+ Get();
+ return (cached_property_serial_ != initial_property_serial_);
+ }
+
+ // Returns the current value of the underlying system property as cheaply as possible.
+ // The returned pointer is valid until the next call to Get. It is the caller's responsibility
+ // to provide a lock for thread-safety.
+ const char* Get() {
+ // Do we have a `struct prop_info` yet?
+ if (prop_info_ == nullptr) {
+ // `__system_property_find` is expensive, so only retry if a property
+ // has been created since last time we checked.
+ uint32_t property_area_serial = __system_property_area_serial();
+ if (property_area_serial != cached_area_serial_) {
+ prop_info_ = __system_property_find(property_name_);
+ cached_area_serial_ = property_area_serial;
+ }
+ }
+
+ if (prop_info_ != nullptr) {
+ // Only bother re-reading the property if it's actually changed since last time.
+ uint32_t property_serial = __system_property_serial(prop_info_);
+ if (property_serial != cached_property_serial_) {
+ __system_property_read_callback(prop_info_, &CachedProperty::Callback, this);
+ }
+ }
+ if (is_read_only_ && read_only_property_ != nullptr) {
+ return read_only_property_;
+ }
+ return cached_value_;
+ }
+
+ private:
+ const char* property_name_;
+ const prop_info* prop_info_;
+ uint32_t cached_area_serial_;
+ uint32_t cached_property_serial_;
+ char cached_value_[PROP_VALUE_MAX];
+ bool is_read_only_;
+ const char* read_only_property_;
+
+ static void Callback(void* data, const char*, const char* value, uint32_t serial) {
+ CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
+ instance->cached_property_serial_ = serial;
+ // Read only properties can be larger than PROP_VALUE_MAX, but also never change value or
+ // location, thus we return the pointer from the shared memory directly.
+ if (instance->is_read_only_) {
+ instance->read_only_property_ = value;
+ } else {
+ strlcpy(instance->cached_value_, value, PROP_VALUE_MAX);
+ }
+ }
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/ErrnoRestorer.h
^
|
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <errno.h>
+
+#include "bionic_macros.h"
+
+class ErrnoRestorer {
+ public:
+ explicit ErrnoRestorer() : saved_errno_(errno) {
+ }
+
+ ~ErrnoRestorer() {
+ errno = saved_errno_;
+ }
+
+ void override(int new_errno) {
+ saved_errno_ = new_errno;
+ }
+
+ private:
+ int saved_errno_;
+
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/FdPath.h
^
|
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+class FdPath {
+ public:
+ explicit FdPath(int fd) {
+ snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
+ }
+
+ const char* c_str() {
+ return buf;
+ }
+
+ private:
+ char buf[40];
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/KernelArgumentBlock.h
^
|
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <elf.h>
+#include <link.h>
+#include <stdint.h>
+#include <sys/auxv.h>
+
+#include "private/bionic_macros.h"
+
+// When the kernel starts the dynamic linker, it passes a pointer to a block
+// of memory containing argc, the argv array, the environment variable array,
+// and the array of ELF aux vectors. This class breaks that block up into its
+// constituents for easy access.
+class KernelArgumentBlock {
+ public:
+ explicit KernelArgumentBlock(void* raw_args) {
+ uintptr_t* args = reinterpret_cast<uintptr_t*>(raw_args);
+ argc = static_cast<int>(*args);
+ argv = reinterpret_cast<char**>(args + 1);
+ envp = argv + argc + 1;
+
+ // Skip over all environment variable definitions to find the aux vector.
+ // The end of the environment block is marked by a NULL pointer.
+ char** p = envp;
+ while (*p != nullptr) {
+ ++p;
+ }
+ ++p; // Skip the NULL itself.
+
+ auxv = reinterpret_cast<ElfW(auxv_t)*>(p);
+ }
+
+ // Similar to ::getauxval but doesn't require the libc global variables to be set up,
+ // so it's safe to call this really early on.
+ unsigned long getauxval(unsigned long type) {
+ for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) {
+ if (v->a_type == type) {
+ return v->a_un.a_val;
+ }
+ }
+ return 0;
+ }
+
+ int argc;
+ char** argv;
+ char** envp;
+ ElfW(auxv_t)* auxv;
+
+ private:
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/MallocXmlElem.h
^
|
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <private/bionic_macros.h>
+
+class MallocXmlElem {
+ public:
+ // Name must be valid throughout lifetime of the object.
+ explicit MallocXmlElem(FILE* fp, const char* name,
+ const char* attr_fmt = nullptr, ...) : fp_(fp), name_(name) {
+ fprintf(fp, "<%s", name_);
+ if (attr_fmt != nullptr) {
+ va_list args;
+ va_start(args, attr_fmt);
+ fputc(' ', fp_);
+ vfprintf(fp_, attr_fmt, args);
+ va_end(args);
+ }
+ fputc('>', fp_);
+ }
+
+ ~MallocXmlElem() noexcept {
+ fprintf(fp_, "</%s>", name_);
+ }
+
+ void Contents(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(fp_, fmt, args);
+ va_end(args);
+ }
+
+private:
+ FILE* fp_;
+ const char* name_;
+
+ BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(MallocXmlElem);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/NetdClientDispatch.h
^
|
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PRIVATE_NETD_CLIENT_DISPATCH_H
+#define PRIVATE_NETD_CLIENT_DISPATCH_H
+
+#include <sys/cdefs.h>
+#include <sys/socket.h>
+
+__BEGIN_DECLS
+
+struct NetdClientDispatch {
+ int (*accept4)(int, struct sockaddr*, socklen_t*, int);
+ int (*connect)(int, const struct sockaddr*, socklen_t);
+ int (*socket)(int, int, int);
+ unsigned (*netIdForResolv)(unsigned);
+ int (*dnsOpenProxy)();
+};
+
+extern __LIBC_HIDDEN__ struct NetdClientDispatch __netdClientDispatch;
+
+__END_DECLS
+
+#endif // PRIVATE_NETD_CLIENT_DISPATCH_H
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/ScopedPthreadMutexLocker.h
^
|
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+#include "bionic_macros.h"
+
+class ScopedPthreadMutexLocker {
+ public:
+ explicit ScopedPthreadMutexLocker(pthread_mutex_t* mu) : mu_(mu) {
+ pthread_mutex_lock(mu_);
+ }
+
+ ~ScopedPthreadMutexLocker() {
+ pthread_mutex_unlock(mu_);
+ }
+
+ private:
+ pthread_mutex_t* mu_;
+
+ BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPthreadMutexLocker);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/ScopedRWLock.h
^
|
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+#include "private/bionic_macros.h"
+
+template <bool write> class ScopedRWLock {
+ public:
+ explicit ScopedRWLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
+ (write ? pthread_rwlock_wrlock : pthread_rwlock_rdlock)(rwlock_);
+ }
+
+ ~ScopedRWLock() {
+ pthread_rwlock_unlock(rwlock_);
+ }
+
+ private:
+ pthread_rwlock_t* rwlock_;
+ BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
+};
+
+typedef ScopedRWLock<true> ScopedWriteLock;
+typedef ScopedRWLock<false> ScopedReadLock;
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/ScopedReaddir.h
^
|
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <dirent.h>
+
+#include "private/bionic_macros.h"
+
+class ScopedReaddir {
+ public:
+ explicit ScopedReaddir(const char* path) : ScopedReaddir(opendir(path)) {
+ }
+
+ explicit ScopedReaddir(DIR* dir) {
+ dir_ = dir;
+ }
+
+ ~ScopedReaddir() {
+ if (dir_ != nullptr) {
+ closedir(dir_);
+ }
+ }
+
+ bool IsBad() {
+ return dir_ == nullptr;
+ }
+
+ dirent* ReadEntry() {
+ return readdir(dir_);
+ }
+
+ private:
+ DIR* dir_;
+
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedReaddir);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/ScopedSignalBlocker.h
^
|
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <signal.h>
+
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "bionic_macros.h"
+
+
+#ifndef _KERNEL__NSIG
+#define _KERNEL__NSIG 64
+#endif
+
+/* Userspace's NSIG is the kernel's _NSIG + 1. */
+#define _NSIG (_KERNEL__NSIG + 1)
+#define NSIG _NSIG
+
+typedef int sig_atomic_t;
+
+typedef __sighandler_t sig_t; /* BSD compatibility. */
+typedef __sighandler_t sighandler_t; /* glibc compatibility. */
+
+#if defined(__LP64__) || defined(__mips__)
+typedef sigset_t sigset64_t;
+#else
+typedef struct { unsigned long __bits[_KERNEL__NSIG/LONG_BIT]; } sigset64_t;
+#endif
+
+
+#define BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+
+class ScopedSignalBlocker {
+ public:
+ // Block all signals.
+ explicit ScopedSignalBlocker() {
+ //sigfillset64(&set);
+ //sigprocmask64(SIG_BLOCK, &set, &old_set_);
+ sigset_t mask;
+ sigfillset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, &old_mask);
+ }
+
+ // Block just the specified signal.
+ explicit ScopedSignalBlocker(int signal) {
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, signal);
+ sigprocmask(SIG_SETMASK, &mask, &old_mask);
+ //sigaddset64(&mask, signal);
+ //sigprocmask64(SIG_BLOCK, &set, &old_set_);
+ }
+
+ ~ScopedSignalBlocker() {
+ reset();
+ }
+
+ void reset() {
+ //sigprocmask64(SIG_SETMASK, &old_set_, nullptr);
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
+ }
+
+ //sigset64_t old_set_;
+ sigset_t old_mask;
+
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/ScopedSignalHandler.h
^
|
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <signal.h>
+
+class ScopedSignalHandler {
+ public:
+ ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0)
+ : signal_number_(signal_number) {
+ action_ = { .sa_flags = sa_flags, .sa_handler = handler };
+ sigaction64(signal_number_, &action_, &old_action_);
+ }
+
+ ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*),
+ int sa_flags = SA_SIGINFO)
+ : signal_number_(signal_number) {
+ action_ = { .sa_flags = sa_flags, .sa_sigaction = action };
+ sigaction64(signal_number_, &action_, &old_action_);
+ }
+
+ explicit ScopedSignalHandler(int signal_number) : signal_number_(signal_number) {
+ sigaction64(signal_number, nullptr, &old_action_);
+ }
+
+ ~ScopedSignalHandler() {
+ sigaction64(signal_number_, &old_action_, nullptr);
+ }
+
+ struct sigaction64 action_;
+ struct sigaction64 old_action_;
+ const int signal_number_;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/SigSetConverter.h
^
|
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+union SigSetConverter {
+ int bsd;
+ sigset_t sigset;
+ sigset64_t sigset64;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/WriteProtected.h
^
|
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "../../../hybris_compat.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+
+#include <async_safe/log.h>
+
+#include "private/bionic_macros.h"
+
+template <typename T>
+union WriteProtectedContents {
+ T value;
+ char padding[PAGE_SIZE];
+
+ WriteProtectedContents() = default;
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtectedContents);
+} __attribute__((aligned(PAGE_SIZE)));
+
+// Write protected wrapper class that aligns its contents to a page boundary,
+// and sets the memory protection to be non-writable, except when being modified
+// explicitly.
+template <typename T>
+class WriteProtected {
+ static_assert(sizeof(T) < PAGE_SIZE,
+ "WriteProtected only supports contents up to PAGE_SIZE");
+ static_assert(__is_pod(T), "WriteProtected only supports POD contents");
+
+ WriteProtectedContents<T> contents;
+
+ public:
+ WriteProtected() = default;
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
+
+ void initialize() {
+ // Not strictly necessary, but this will hopefully segfault if we initialize
+ // multiple times by accident.
+ memset(&contents, 0, sizeof(contents));
+
+ if (mprotect(&contents, PAGE_SIZE, PROT_READ)) {
+ async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
+ }
+ }
+
+ const T* operator->() {
+ return &contents.value;
+ }
+
+ const T& operator*() {
+ return contents.value;
+ }
+
+ template <typename Mutator>
+ void mutate(Mutator mutator) {
+ if (mprotect(&contents, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
+ async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
+ strerror(errno));
+ }
+ mutator(&contents.value);
+ if (mprotect(&contents, PAGE_SIZE, PROT_READ) != 0) {
+ async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
+ strerror(errno));
+ }
+ }
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/__bionic_get_shell_path.h
^
|
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+extern "C" const char* __bionic_get_shell_path();
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/__get_tls.h
^
|
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __BIONIC_PRIVATE_GET_TLS_H_
+#define __BIONIC_PRIVATE_GET_TLS_H_
+
+#if defined(__aarch64__)
+# define __get_tls() ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; })
+#elif defined(__arm__)
+# define __get_tls() ({ void** __val; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); __val; })
+#elif defined(__mips__)
+# define __get_tls() \
+ /* On mips32r1, this goes via a kernel illegal instruction trap that's optimized for v1. */ \
+ ({ register void** __val asm("v1"); \
+ __asm__(".set push\n" \
+ ".set mips32r2\n" \
+ "rdhwr %0,$29\n" \
+ ".set pop\n" : "=r"(__val)); \
+ __val; })
+#elif defined(__i386__)
+# define __get_tls() ({ void** __val; __asm__("movl %%gs:0, %0" : "=r"(__val)); __val; })
+#elif defined(__x86_64__)
+# define __get_tls() ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; })
+#else
+#error unsupported architecture
+#endif
+
+#endif /* __BIONIC_PRIVATE_GET_TLS_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_allocator.h
^
|
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <stdint.h>
+
+const uint32_t kSmallObjectMaxSizeLog2 = 10;
+const uint32_t kSmallObjectMinSizeLog2 = 4;
+const uint32_t kSmallObjectAllocatorsCount = kSmallObjectMaxSizeLog2 - kSmallObjectMinSizeLog2 + 1;
+
+class BionicSmallObjectAllocator;
+
+// This structure is placed at the beginning of each addressable page
+// and has all information we need to find the corresponding memory allocator.
+struct page_info {
+ char signature[4];
+ uint32_t type;
+ union {
+ // we use allocated_size for large objects allocator
+ size_t allocated_size;
+ // and allocator_addr for small ones.
+ BionicSmallObjectAllocator* allocator_addr;
+ };
+};
+
+struct small_object_block_record {
+ small_object_block_record* next;
+ size_t free_blocks_cnt;
+};
+
+// This structure is placed at the beginning of each page managed by
+// BionicSmallObjectAllocator. Note that a page_info struct is expected at the
+// beginning of each page as well, and therefore this structure contains a
+// page_info as its *first* field.
+struct small_object_page_info {
+ page_info info; // Must be the first field.
+
+ // Doubly linked list for traversing all pages allocated by a
+ // BionicSmallObjectAllocator.
+ small_object_page_info* next_page;
+ small_object_page_info* prev_page;
+
+ // Linked list containing all free blocks in this page.
+ small_object_block_record* free_block_list;
+
+ // Free blocks counter.
+ size_t free_blocks_cnt;
+};
+
+class BionicSmallObjectAllocator {
+ public:
+ BionicSmallObjectAllocator(uint32_t type, size_t block_size);
+ void* alloc();
+ void free(void* ptr);
+
+ size_t get_block_size() const { return block_size_; }
+ private:
+ void alloc_page();
+ void free_page(small_object_page_info* page);
+ void add_to_page_list(small_object_page_info* page);
+ void remove_from_page_list(small_object_page_info* page);
+
+ const uint32_t type_;
+ const size_t block_size_;
+ const size_t blocks_per_page_;
+
+ size_t free_pages_cnt_;
+
+ small_object_page_info* page_list_;
+};
+
+class BionicAllocator {
+ public:
+ constexpr BionicAllocator() : allocators_(nullptr), allocators_buf_() {}
+ void* alloc(size_t size);
+ void* memalign(size_t align, size_t size);
+
+ // Note that this implementation of realloc never shrinks allocation
+ void* realloc(void* ptr, size_t size);
+ void free(void* ptr);
+ private:
+ void* alloc_mmap(size_t align, size_t size);
+ inline void* alloc_impl(size_t align, size_t size);
+ inline page_info* get_page_info_unchecked(void* ptr);
+ inline page_info* get_page_info(void* ptr);
+ BionicSmallObjectAllocator* get_small_object_allocator(uint32_t type);
+ void initialize_allocators();
+
+ BionicSmallObjectAllocator* allocators_;
+ uint8_t allocators_buf_[sizeof(BionicSmallObjectAllocator)*kSmallObjectAllocatorsCount];
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_arc4random.h
^
|
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_BIONIC_ARC4RANDOM_H_
+#define _PRIVATE_BIONIC_ARC4RANDOM_H_
+
+#include <stddef.h>
+
+// arc4random(3) aborts if it's unable to fetch entropy, which is always
+// the case for init on devices. GCE kernels have a workaround to ensure
+// sufficient entropy during early boot, but no device kernels do. This
+// wrapper falls back to AT_RANDOM if the kernel doesn't have enough
+// entropy for getrandom(2) or /dev/urandom.
+void __libc_safe_arc4random_buf(void* buf, size_t n);
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm.h
^
|
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_BIONIC_ASM_H_
+#define _PRIVATE_BIONIC_ASM_H_
+
+#include <asm/unistd.h> /* For system call numbers. */
+#define MAX_ERRNO 4095 /* For recognizing system call error returns. */
+
+#define __bionic_asm_custom_entry(f)
+#define __bionic_asm_custom_end(f)
+#define __bionic_asm_function_type @function
+
+#if defined(__aarch64__)
+#include <private/bionic_asm_arm64.h>
+#elif defined(__arm__)
+#include <private/bionic_asm_arm.h>
+#elif defined(__i386__)
+#include <private/bionic_asm_x86.h>
+#elif defined(__mips__)
+#include <private/bionic_asm_mips.h>
+#elif defined(__x86_64__)
+#include <private/bionic_asm_x86_64.h>
+#endif
+
+#define ENTRY_NO_DWARF(f) \
+ .text; \
+ .globl f; \
+ .balign __bionic_asm_align; \
+ .type f, __bionic_asm_function_type; \
+ f: \
+ __bionic_asm_custom_entry(f); \
+
+#define ENTRY(f) \
+ ENTRY_NO_DWARF(f) \
+ .cfi_startproc \
+
+#define END_NO_DWARF(f) \
+ .size f, .-f; \
+ __bionic_asm_custom_end(f) \
+
+#define END(f) \
+ .cfi_endproc; \
+ END_NO_DWARF(f) \
+
+/* Like ENTRY, but with hidden visibility. */
+#define ENTRY_PRIVATE(f) \
+ ENTRY(f); \
+ .hidden f \
+
+/* Like ENTRY_NO_DWARF, but with hidden visibility. */
+#define ENTRY_PRIVATE_NO_DWARF(f) \
+ ENTRY_NO_DWARF(f); \
+ .hidden f \
+
+#define __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(f) \
+ .weak f; \
+
+#define ALIAS_SYMBOL(alias, original) \
+ .globl alias; \
+ .equ alias, original
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm_arm.h
^
|
@@ -0,0 +1,48 @@
+/* $OpenBSD: asm.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */
+/* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#pragma once
+
+#define __bionic_asm_align 0
+
+#undef __bionic_asm_custom_entry
+#undef __bionic_asm_custom_end
+#define __bionic_asm_custom_entry(f) .fnstart
+#define __bionic_asm_custom_end(f) .fnend
+
+#undef __bionic_asm_function_type
+#define __bionic_asm_function_type #function
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm_arm64.h
^
|
@@ -0,0 +1,43 @@
+/* $OpenBSD: asm.h,v 1.1 2004/02/01 05:09:49 drahn Exp $ */
+/* $NetBSD: asm.h,v 1.4 2001/07/16 05:43:32 matt Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#pragma once
+
+#define __bionic_asm_align 16
+
+#undef __bionic_asm_function_type
+#define __bionic_asm_function_type %function
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm_mips.h
^
|
@@ -0,0 +1,187 @@
+/* $OpenBSD: asm.h,v 1.7 2004/10/20 12:49:15 pefo Exp $ */
+
+/*
+ * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#define __bionic_asm_align 16
+
+#undef __bionic_asm_custom_entry
+#undef __bionic_asm_custom_end
+#define __bionic_asm_custom_entry(f) .ent f
+#define __bionic_asm_custom_end(f) .end f
+
+#define _MIPS_ISA_MIPS1 1 /* R2000/R3000 */
+#define _MIPS_ISA_MIPS2 2 /* R4000/R6000 */
+#define _MIPS_ISA_MIPS3 3 /* R4000 */
+#define _MIPS_ISA_MIPS4 4 /* TFP (R1x000) */
+#define _MIPS_ISA_MIPS5 5
+#define _MIPS_ISA_MIPS32 6
+#define _MIPS_ISA_MIPS64 7
+
+#if !defined(ABICALLS) && !defined(_NO_ABICALLS)
+#define ABICALLS .abicalls
+#endif
+
+#if defined(ABICALLS) && !defined(_KERNEL)
+ ABICALLS
+#endif
+
+/*
+ * Define how to access unaligned data word
+ */
+#define LWLO lwl
+#define LWHI lwr
+#define SWLO swl
+#define SWHI swr
+#define LDLO ldl
+#define LDHI ldr
+#define SDLO sdl
+#define SDHI sdr
+
+/*
+ * Define programming environment for ABI.
+ */
+#if defined(ABICALLS) && !defined(_KERNEL) && !defined(_STANDALONE)
+
+#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)
+#define NARGSAVE 4
+
+#define SETUP_GP \
+ .set noreorder; \
+ .cpload $t9; \
+ .set reorder;
+
+#define SAVE_GP(x) \
+ .cprestore x
+
+#define SETUP_GP64(gpoff, name)
+#define RESTORE_GP64
+#endif
+
+#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32)
+#define NARGSAVE 0
+
+#define SETUP_GP
+#define SAVE_GP(x)
+#define SETUP_GP64(gpoff, name) \
+ .cpsetup $t9, gpoff, name
+#define RESTORE_GP64 \
+ .cpreturn
+#endif
+
+#define MKFSIZ(narg,locals) (((narg+locals)*REGSZ+31)&(~31))
+
+#else /* defined(ABICALLS) && !defined(_KERNEL) */
+
+#define NARGSAVE 4
+#define SETUP_GP
+#define SAVE_GP(x)
+
+#define ALIGNSZ 16 /* Stack layout alignment */
+#define FRAMESZ(sz) (((sz) + (ALIGNSZ-1)) & ~(ALIGNSZ-1))
+
+#endif
+
+/*
+ * Basic register operations based on selected ISA
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || _MIPS_ISA == _MIPS_ISA_MIPS32)
+#define REGSZ 4 /* 32 bit mode register size */
+#define LOGREGSZ 2 /* log rsize */
+#define REG_S sw
+#define REG_L lw
+#define CF_SZ 24 /* Call frame size */
+#define CF_ARGSZ 16 /* Call frame arg size */
+#define CF_RA_OFFS 20 /* Call ra save offset */
+#endif
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || _MIPS_ISA == _MIPS_ISA_MIPS64)
+#define REGSZ 8 /* 64 bit mode register size */
+#define LOGREGSZ 3 /* log rsize */
+#define REG_S sd
+#define REG_L ld
+#define CF_SZ 48 /* Call frame size (multiple of ALIGNSZ) */
+#define CF_ARGSZ 32 /* Call frame arg size */
+#define CF_RA_OFFS 40 /* Call ra save offset */
+#endif
+
+#define REGSZ_FP 8 /* 64 bit FP register size */
+
+#ifndef __LP64__
+#define PTR_L lw
+#define PTR_S sw
+#define PTR_SUB sub
+#define PTR_ADD add
+#define PTR_SUBU subu
+#define PTR_ADDU addu
+#define LI li
+#define LA la
+#define PTR_SLL sll
+#define PTR_SRL srl
+#define PTR_VAL .word
+#else
+#define PTR_L ld
+#define PTR_S sd
+#define PTR_ADD dadd
+#define PTR_SUB dsub
+#define PTR_SUBU dsubu
+#define PTR_ADDU daddu
+#define LI dli
+#define LA dla
+#define PTR_SLL dsll
+#define PTR_SRL dsrl
+#define PTR_VAL .dword
+#endif
+
+/*
+ * LEAF(x, fsize)
+ *
+ * Declare a leaf routine.
+ */
+#define LEAF(x, fsize) \
+ .align 3; \
+ .globl x; \
+ .ent x, 0; \
+x: ; \
+ .cfi_startproc; \
+ .frame $sp, fsize, $ra; \
+ SETUP_GP \
+
+/*
+ * NON_LEAF(x)
+ *
+ * Declare a non-leaf routine (a routine that makes other C calls).
+ */
+#define NON_LEAF(x, fsize, retpc) \
+ .align 3; \
+ .globl x; \
+ .ent x, 0; \
+x: ; \
+ .cfi_startproc; \
+ .frame $sp, fsize, retpc; \
+ SETUP_GP \
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm_tls.h
^
|
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+/** WARNING WARNING WARNING
+ **
+ ** This header file is *NOT* part of the public Bionic ABI/API and should not
+ ** be used/included by user-serviceable parts of the system (e.g.
+ ** applications).
+ **
+ ** It is only provided here for the benefit of Android components that need a
+ ** pre-allocated slot for performance reasons (including ART, the OpenGL
+ ** subsystem, and sanitizers).
+ **/
+
+// Bionic TCB / TLS slots:
+//
+// - TLS_SLOT_SELF: On x86-{32,64}, the kernel makes TLS memory available via
+// the gs/fs segments. To get the address of a TLS variable, the first slot
+// of TLS memory (accessed using %gs:0 / %fs:0) holds the address of the
+// gs/fs segment. This slot is used by:
+// - OpenGL and compiler-rt
+// - Accesses of x86 ELF TLS variables
+//
+// - TLS_SLOT_OPENGL and TLS_SLOT_OPENGL_API: These two aren't used by bionic
+// itself, but allow the graphics code to access TLS directly rather than
+// using the pthread API.
+//
+// - TLS_SLOT_STACK_GUARD: Used for -fstack-protector by:
+// - Clang targeting Android/arm64
+// - gcc targeting Linux/x86-{32,64}
+//
+// - TLS_SLOT_SANITIZER: Lets sanitizers avoid using pthread_getspecific for
+// finding the current thread state.
+//
+// - TLS_SLOT_DTV: Pointer to ELF TLS dynamic thread vector.
+//
+// - TLS_SLOT_ART_THREAD_SELF: Fast storage for Thread::Current() in ART.
+//
+// - TLS_SLOT_BIONIC_TLS: Optimizes accesses to bionic_tls by one load versus
+// finding it using __get_thread().
+//
+// - TLS_SLOT_APP: Available for use by apps in Android Q and later. (This slot
+// was used for errno in P and earlier.)
+
+#if defined(__arm__) || defined(__aarch64__)
+
+// The ARM ELF TLS ABI specifies[1] that the thread pointer points at a 2-word
+// TCB followed by the executable's TLS segment. Both the TCB and the
+// executable's segment are aligned according to the segment, so Bionic requires
+// a minimum segment alignment, which effectively reserves an 8-word TCB. The
+// ARM spec allocates the first TCB word to the DTV.
+//
+// [1] "Addenda to, and Errata in, the ABI for the ARM Architecture". Section 3.
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045e/IHI0045E_ABI_addenda.pdf
+
+#define MIN_TLS_SLOT -1 // update this value when reserving a slot
+#define TLS_SLOT_BIONIC_TLS -1
+#define TLS_SLOT_DTV 0
+#define TLS_SLOT_THREAD_ID 1
+#define TLS_SLOT_APP 2 // was historically used for errno
+#define TLS_SLOT_OPENGL 3
+#define TLS_SLOT_OPENGL_API 4
+#define TLS_SLOT_STACK_GUARD 5
+#define TLS_SLOT_SANITIZER 6 // was historically used for dlerror
+#define TLS_SLOT_ART_THREAD_SELF 7
+
+// The maximum slot is fixed by the minimum TLS alignment in Bionic executables.
+#define MAX_TLS_SLOT 7
+
+#elif defined(__i386__) || defined(__x86_64__)
+
+// x86 uses variant 2 ELF TLS layout, which places the executable's TLS segment
+// immediately before the thread pointer. New slots are allocated at positive
+// offsets from the thread pointer.
+
+#define MIN_TLS_SLOT 0
+
+#define TLS_SLOT_SELF 0
+#define TLS_SLOT_THREAD_ID 1
+#define TLS_SLOT_APP 2 // was historically used for errno
+#define TLS_SLOT_OPENGL 3
+#define TLS_SLOT_OPENGL_API 4
+#define TLS_SLOT_STACK_GUARD 5
+#define TLS_SLOT_SANITIZER 6 // was historically used for dlerror
+#define TLS_SLOT_ART_THREAD_SELF 7
+#define TLS_SLOT_DTV 8
+#define TLS_SLOT_BIONIC_TLS 9
+#define MAX_TLS_SLOT 9 // update this value when reserving a slot
+
+#endif
+
+#define BIONIC_TLS_SLOTS (MAX_TLS_SLOT - MIN_TLS_SLOT + 1)
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm_x86.h
^
|
@@ -0,0 +1,51 @@
+/* $NetBSD: asm.h,v 1.40 2011/06/16 13:16:20 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#pragma once
+
+#define PIC_PROLOGUE \
+ pushl %ebx; \
+ call 666f; \
+666: \
+ popl %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+[.-666b], %ebx
+#define PIC_EPILOGUE \
+ popl %ebx
+#define PIC_PLT(x) x@PLT
+#define PIC_GOT(x) x@GOT(%ebx)
+#define PIC_GOTOFF(x) x@GOTOFF(%ebx)
+
+#define __bionic_asm_align 16
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_asm_x86_64.h
^
|
@@ -0,0 +1,42 @@
+/* $NetBSD: asm.h,v 1.18 2013/09/12 15:36:17 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#pragma once
+
+#define PIC_PLT(x) x@PLT
+#define PIC_GOT(x) x@GOTPCREL(%rip)
+
+#define __bionic_asm_align 16
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_auxv.h
^
|
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists);
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_config.h
^
|
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_CONFIG_H_
+#define _BIONIC_CONFIG_H_
+
+// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them
+// for LP64, but the symbols remain in LP32 for binary compatibility.
+#if !defined(__LP64__)
+#define HAVE_DEPRECATED_MALLOC_FUNCS 1
+#endif
+
+#endif // _BIONIC_CONFIG_H_
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_constants.h
^
|
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_CONSTANTS_H_
+#define _BIONIC_CONSTANTS_H_
+
+#define NS_PER_S 1000000000
+
+// Size of the shadow call stack. This must be a power of 2.
+#define SCS_SIZE (8 * 1024)
+
+// The shadow call stack is allocated at an aligned address within a guard region of this size. The
+// guard region must be large enough that we can allocate an SCS_SIZE-aligned SCS while ensuring
+// that there is at least one guard page after the SCS so that a stack overflow results in a SIGSEGV
+// instead of corrupting the allocation that comes after it.
+#define SCS_GUARD_REGION_SIZE (16 * 1024 * 1024)
+
+#endif // _BIONIC_CONSTANTS_H_
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_ctype.h
^
|
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __BIONIC_PRIVATE_BIONIC_CTYPE_H_
+#define __BIONIC_PRIVATE_BIONIC_CTYPE_H_
+
+static inline bool IsAlpha(int ch) {
+ return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+}
+
+static inline bool IsDigit(int ch) {
+ return (ch >= '0' && ch <= '9');
+}
+
+static inline bool IsSpace(int ch) {
+ return (ch == ' ') || (ch >= '\t' && ch <= '\r');
+}
+
+static inline bool IsUpper(int ch) {
+ return (ch >= 'A' && ch <= 'Z');
+}
+
+static inline bool IsXDigit(int ch) {
+ return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
+}
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_defs.h
^
|
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __BIONIC_PRIVATE_BIONIC_DEFS_H_
+#define __BIONIC_PRIVATE_BIONIC_DEFS_H_
+
+/*
+ * This label is used to mark libc/libdl symbols that may need to be replaced
+ * by native bridge implementation.
+ */
+#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE __attribute__((__weak__, __noinline__))
+#define __BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE __attribute__((__weak__))
+
+#endif /* __BIONIC_PRIVATE_BIONIC_DEFS_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_elf_tls.h
^
|
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <link.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <stdint.h>
+#include <sys/cdefs-android.h>
+
+__LIBC_HIDDEN__ extern _Atomic(size_t) __libc_tls_generation_copy;
+
+struct TlsSegment {
+ size_t size = 0;
+ size_t alignment = 1;
+ const void* init_ptr = ""; // Field is non-null even when init_size is 0.
+ size_t init_size = 0;
+};
+
+__LIBC_HIDDEN__ bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, TlsSegment* out);
+
+__LIBC_HIDDEN__ bool __bionic_check_tls_alignment(size_t* alignment);
+
+struct StaticTlsLayout {
+ constexpr StaticTlsLayout() {}
+
+private:
+ size_t offset_ = 0;
+ size_t alignment_ = 1;
+ bool overflowed_ = false;
+
+ // Offsets to various Bionic TLS structs from the beginning of static TLS.
+ size_t offset_bionic_tcb_ = SIZE_MAX;
+ size_t offset_bionic_tls_ = SIZE_MAX;
+
+public:
+ size_t offset_bionic_tcb() const { return offset_bionic_tcb_; }
+ size_t offset_bionic_tls() const { return offset_bionic_tls_; }
+ size_t offset_thread_pointer() const;
+
+ size_t size() const { return offset_; }
+ size_t alignment() const { return alignment_; }
+ bool overflowed() const { return overflowed_; }
+
+ size_t reserve_exe_segment_and_tcb(const TlsSegment* exe_segment, const char* progname);
+ void reserve_bionic_tls();
+ size_t reserve_solib_segment(const TlsSegment& segment) {
+ return reserve(segment.size, segment.alignment);
+ }
+ void finish_layout();
+
+private:
+ size_t reserve(size_t size, size_t alignment);
+
+ template <typename T> size_t reserve_type() {
+ return reserve(sizeof(T), alignof(T));
+ }
+
+ size_t round_up_with_overflow_check(size_t value, size_t alignment);
+};
+
+static constexpr size_t kTlsGenerationNone = 0;
+static constexpr size_t kTlsGenerationFirst = 1;
+
+// The first ELF TLS module has ID 1. Zero is reserved for the first word of
+// the DTV, a generation count. Unresolved weak symbols also use module ID 0.
+static constexpr size_t kTlsUninitializedModuleId = 0;
+
+static inline size_t __tls_module_id_to_idx(size_t id) { return id - 1; }
+static inline size_t __tls_module_idx_to_id(size_t idx) { return idx + 1; }
+
+// A descriptor for a single ELF TLS module.
+struct TlsModule {
+ TlsSegment segment;
+
+ // Offset into the static TLS block or SIZE_MAX for a dynamic module.
+ size_t static_offset = SIZE_MAX;
+
+ // The generation in which this module was loaded. Dynamic TLS lookups use
+ // this field to detect when a module has been unloaded.
+ size_t first_generation = kTlsGenerationNone;
+
+ // Used by the dynamic linker to track the associated soinfo* object.
+ void* soinfo_ptr = nullptr;
+};
+
+// Table of the ELF TLS modules. Either the dynamic linker or the static
+// initialization code prepares this table, and it's then used during thread
+// creation and for dynamic TLS lookups.
+struct TlsModules {
+ constexpr TlsModules() {}
+
+ // A pointer to the TLS generation counter in libc.so. The counter is
+ // incremented each time an solib is loaded or unloaded.
+ _Atomic(size_t) generation = {kTlsGenerationFirst};
+ _Atomic(size_t) *generation_libc_so = nullptr;
+
+ // Access to the TlsModule[] table requires taking this lock.
+ pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+ // Pointer to a block of TlsModule objects. The first module has ID 1 and
+ // is stored at index 0 in this table.
+ size_t module_count = 0;
+ TlsModule* module_table = nullptr;
+};
+
+void __init_static_tls(void* static_tls);
+
+// Dynamic Thread Vector. Each thread has a different DTV. For each module
+// (executable or solib), the DTV has a pointer to that module's TLS memory. The
+// DTV is initially empty and is allocated on-demand. It grows as more modules
+// are dlopen'ed. See https://www.akkadia.org/drepper/tls.pdf.
+//
+// The layout of the DTV is specified in various documents, but it is not part
+// of Bionic's public ABI. A compiler can't generate code to access it directly,
+// because it can't access libc's global generation counter.
+struct TlsDtv {
+ // Number of elements in this object's modules field.
+ size_t count;
+
+ // A pointer to an older TlsDtv object that should be freed when the thread
+ // exits. The objects aren't immediately freed because a DTV could be
+ // reallocated by a signal handler that interrupted __tls_get_addr's fast
+ // path.
+ TlsDtv* next;
+
+ // The DTV slot points at this field, which allows omitting an add instruction
+ // on the fast path for a TLS lookup. The arm64 tlsdesc_resolver.S depends on
+ // the layout of fields past this point.
+ size_t generation;
+ void* modules[];
+};
+
+struct TlsIndex {
+ size_t module_id;
+ size_t offset;
+};
+
+#if defined(__i386__)
+#define TLS_GET_ADDR_CCONV __attribute__((regparm(1)))
+#define TLS_GET_ADDR ___tls_get_addr
+#else
+#define TLS_GET_ADDR_CCONV
+#define TLS_GET_ADDR __tls_get_addr
+#endif
+
+extern "C" void* TLS_GET_ADDR(const TlsIndex* ti) TLS_GET_ADDR_CCONV;
+
+struct bionic_tcb;
+void __free_dynamic_tls(bionic_tcb* tcb);
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_errdefs.h
^
|
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* the following corresponds to the error codes of the Linux kernel used by the Android platform
+ * these are distinct from the OpenBSD ones, which is why we need to redeclare them here
+ *
+ * this file may be included several times to define either error constants or their
+ * string representation
+ */
+
+#ifndef __BIONIC_ERRDEF
+#error "__BIONIC_ERRDEF must be defined before including this file"
+#endif
+__BIONIC_ERRDEF( 0 , 0, "Success" )
+__BIONIC_ERRDEF( EPERM , 1, "Operation not permitted" )
+__BIONIC_ERRDEF( ENOENT , 2, "No such file or directory" )
+__BIONIC_ERRDEF( ESRCH , 3, "No such process" )
+__BIONIC_ERRDEF( EINTR , 4, "Interrupted system call" )
+__BIONIC_ERRDEF( EIO , 5, "I/O error" )
+__BIONIC_ERRDEF( ENXIO , 6, "No such device or address" )
+__BIONIC_ERRDEF( E2BIG , 7, "Argument list too long" )
+__BIONIC_ERRDEF( ENOEXEC , 8, "Exec format error" )
+__BIONIC_ERRDEF( EBADF , 9, "Bad file descriptor" )
+__BIONIC_ERRDEF( ECHILD , 10, "No child processes" )
+__BIONIC_ERRDEF( EAGAIN , 11, "Try again" )
+__BIONIC_ERRDEF( ENOMEM , 12, "Out of memory" )
+__BIONIC_ERRDEF( EACCES , 13, "Permission denied" )
+__BIONIC_ERRDEF( EFAULT , 14, "Bad address" )
+__BIONIC_ERRDEF( ENOTBLK , 15, "Block device required" )
+__BIONIC_ERRDEF( EBUSY , 16, "Device or resource busy" )
+__BIONIC_ERRDEF( EEXIST , 17, "File exists" )
+__BIONIC_ERRDEF( EXDEV , 18, "Cross-device link" )
+__BIONIC_ERRDEF( ENODEV , 19, "No such device" )
+__BIONIC_ERRDEF( ENOTDIR , 20, "Not a directory" )
+__BIONIC_ERRDEF( EISDIR , 21, "Is a directory" )
+__BIONIC_ERRDEF( EINVAL , 22, "Invalid argument" )
+__BIONIC_ERRDEF( ENFILE , 23, "File table overflow" )
+__BIONIC_ERRDEF( EMFILE , 24, "Too many open files" )
+__BIONIC_ERRDEF( ENOTTY , 25, "Not a typewriter" )
+__BIONIC_ERRDEF( ETXTBSY , 26, "Text file busy" )
+__BIONIC_ERRDEF( EFBIG , 27, "File too large" )
+__BIONIC_ERRDEF( ENOSPC , 28, "No space left on device" )
+__BIONIC_ERRDEF( ESPIPE , 29, "Illegal seek" )
+__BIONIC_ERRDEF( EROFS , 30, "Read-only file system" )
+__BIONIC_ERRDEF( EMLINK , 31, "Too many links" )
+__BIONIC_ERRDEF( EPIPE , 32, "Broken pipe" )
+__BIONIC_ERRDEF( EDOM , 33, "Math argument out of domain of func" )
+__BIONIC_ERRDEF( ERANGE , 34, "Math result not representable" )
+__BIONIC_ERRDEF( EDEADLK , 35, "Resource deadlock would occur" )
+__BIONIC_ERRDEF( ENAMETOOLONG , 36, "File name too long" )
+__BIONIC_ERRDEF( ENOLCK , 37, "No record locks available" )
+__BIONIC_ERRDEF( ENOSYS , 38, "Function not implemented" )
+__BIONIC_ERRDEF( ENOTEMPTY , 39, "Directory not empty" )
+__BIONIC_ERRDEF( ELOOP , 40, "Too many symbolic links encountered" )
+__BIONIC_ERRDEF( ENOMSG , 42, "No message of desired type" )
+__BIONIC_ERRDEF( EIDRM , 43, "Identifier removed" )
+__BIONIC_ERRDEF( ECHRNG , 44, "Channel number out of range" )
+__BIONIC_ERRDEF( EL2NSYNC , 45, "Level 2 not synchronized" )
+__BIONIC_ERRDEF( EL3HLT , 46, "Level 3 halted" )
+__BIONIC_ERRDEF( EL3RST , 47, "Level 3 reset" )
+__BIONIC_ERRDEF( ELNRNG , 48, "Link number out of range" )
+__BIONIC_ERRDEF( EUNATCH , 49, "Protocol driver not attached" )
+__BIONIC_ERRDEF( ENOCSI , 50, "No CSI structure available" )
+__BIONIC_ERRDEF( EL2HLT , 51, "Level 2 halted" )
+__BIONIC_ERRDEF( EBADE , 52, "Invalid exchange" )
+__BIONIC_ERRDEF( EBADR , 53, "Invalid request descriptor" )
+__BIONIC_ERRDEF( EXFULL , 54, "Exchange full" )
+__BIONIC_ERRDEF( ENOANO , 55, "No anode" )
+__BIONIC_ERRDEF( EBADRQC , 56, "Invalid request code" )
+__BIONIC_ERRDEF( EBADSLT , 57, "Invalid slot" )
+__BIONIC_ERRDEF( EBFONT , 59, "Bad font file format" )
+__BIONIC_ERRDEF( ENOSTR , 60, "Device not a stream" )
+__BIONIC_ERRDEF( ENODATA , 61, "No data available" )
+__BIONIC_ERRDEF( ETIME , 62, "Timer expired" )
+__BIONIC_ERRDEF( ENOSR , 63, "Out of streams resources" )
+__BIONIC_ERRDEF( ENONET , 64, "Machine is not on the network" )
+__BIONIC_ERRDEF( ENOPKG , 65, "Package not installed" )
+__BIONIC_ERRDEF( EREMOTE , 66, "Object is remote" )
+__BIONIC_ERRDEF( ENOLINK , 67, "Link has been severed" )
+__BIONIC_ERRDEF( EADV , 68, "Advertise error" )
+__BIONIC_ERRDEF( ESRMNT , 69, "Srmount error" )
+__BIONIC_ERRDEF( ECOMM , 70, "Communication error on send" )
+__BIONIC_ERRDEF( EPROTO , 71, "Protocol error" )
+__BIONIC_ERRDEF( EMULTIHOP , 72, "Multihop attempted" )
+__BIONIC_ERRDEF( EDOTDOT , 73, "RFS specific error" )
+__BIONIC_ERRDEF( EBADMSG , 74, "Not a data message" )
+__BIONIC_ERRDEF( EOVERFLOW , 75, "Value too large for defined data type" )
+__BIONIC_ERRDEF( ENOTUNIQ , 76, "Name not unique on network" )
+__BIONIC_ERRDEF( EBADFD , 77, "File descriptor in bad state" )
+__BIONIC_ERRDEF( EREMCHG , 78, "Remote address changed" )
+__BIONIC_ERRDEF( ELIBACC , 79, "Can not access a needed shared library" )
+__BIONIC_ERRDEF( ELIBBAD , 80, "Accessing a corrupted shared library" )
+__BIONIC_ERRDEF( ELIBSCN , 81, ".lib section in a.out corrupted" )
+__BIONIC_ERRDEF( ELIBMAX , 82, "Attempting to link in too many shared libraries" )
+__BIONIC_ERRDEF( ELIBEXEC , 83, "Cannot exec a shared library directly" )
+__BIONIC_ERRDEF( EILSEQ , 84, "Illegal byte sequence" )
+__BIONIC_ERRDEF( ERESTART , 85, "Interrupted system call should be restarted" )
+__BIONIC_ERRDEF( ESTRPIPE , 86, "Streams pipe error" )
+__BIONIC_ERRDEF( EUSERS , 87, "Too many users" )
+__BIONIC_ERRDEF( ENOTSOCK , 88, "Socket operation on non-socket" )
+__BIONIC_ERRDEF( EDESTADDRREQ , 89, "Destination address required" )
+__BIONIC_ERRDEF( EMSGSIZE , 90, "Message too long" )
+__BIONIC_ERRDEF( EPROTOTYPE , 91, "Protocol wrong type for socket" )
+__BIONIC_ERRDEF( ENOPROTOOPT , 92, "Protocol not available" )
+__BIONIC_ERRDEF( EPROTONOSUPPORT, 93, "Protocol not supported" )
+__BIONIC_ERRDEF( ESOCKTNOSUPPORT, 94, "Socket type not supported" )
+__BIONIC_ERRDEF( EOPNOTSUPP , 95, "Operation not supported on transport endpoint" )
+__BIONIC_ERRDEF( EPFNOSUPPORT , 96, "Protocol family not supported" )
+__BIONIC_ERRDEF( EAFNOSUPPORT , 97, "Address family not supported by protocol" )
+__BIONIC_ERRDEF( EADDRINUSE , 98, "Address already in use" )
+__BIONIC_ERRDEF( EADDRNOTAVAIL , 99, "Cannot assign requested address" )
+__BIONIC_ERRDEF( ENETDOWN , 100, "Network is down" )
+__BIONIC_ERRDEF( ENETUNREACH , 101, "Network is unreachable" )
+__BIONIC_ERRDEF( ENETRESET , 102, "Network dropped connection because of reset" )
+__BIONIC_ERRDEF( ECONNABORTED , 103, "Software caused connection abort" )
+__BIONIC_ERRDEF( ECONNRESET , 104, "Connection reset by peer" )
+__BIONIC_ERRDEF( ENOBUFS , 105, "No buffer space available" )
+__BIONIC_ERRDEF( EISCONN , 106, "Transport endpoint is already connected" )
+__BIONIC_ERRDEF( ENOTCONN , 107, "Transport endpoint is not connected" )
+__BIONIC_ERRDEF( ESHUTDOWN , 108, "Cannot send after transport endpoint shutdown" )
+__BIONIC_ERRDEF( ETOOMANYREFS , 109, "Too many references: cannot splice" )
+__BIONIC_ERRDEF( ETIMEDOUT , 110, "Connection timed out" )
+__BIONIC_ERRDEF( ECONNREFUSED , 111, "Connection refused" )
+__BIONIC_ERRDEF( EHOSTDOWN , 112, "Host is down" )
+__BIONIC_ERRDEF( EHOSTUNREACH , 113, "No route to host" )
+__BIONIC_ERRDEF( EALREADY , 114, "Operation already in progress" )
+__BIONIC_ERRDEF( EINPROGRESS , 115, "Operation now in progress" )
+__BIONIC_ERRDEF( ESTALE , 116, "Stale NFS file handle" )
+__BIONIC_ERRDEF( EUCLEAN , 117, "Structure needs cleaning" )
+__BIONIC_ERRDEF( ENOTNAM , 118, "Not a XENIX named type file" )
+__BIONIC_ERRDEF( ENAVAIL , 119, "No XENIX semaphores available" )
+__BIONIC_ERRDEF( EISNAM , 120, "Is a named type file" )
+__BIONIC_ERRDEF( EREMOTEIO , 121, "Remote I/O error" )
+__BIONIC_ERRDEF( EDQUOT , 122, "Quota exceeded" )
+__BIONIC_ERRDEF( ENOMEDIUM , 123, "No medium found" )
+__BIONIC_ERRDEF( EMEDIUMTYPE , 124, "Wrong medium type" )
+__BIONIC_ERRDEF( ECANCELED , 125, "Operation Canceled" )
+__BIONIC_ERRDEF( ENOKEY , 126, "Required key not available" )
+__BIONIC_ERRDEF( EKEYEXPIRED , 127, "Key has expired" )
+__BIONIC_ERRDEF( EKEYREVOKED , 128, "Key has been revoked" )
+__BIONIC_ERRDEF( EKEYREJECTED , 129, "Key was rejected by service" )
+__BIONIC_ERRDEF( EOWNERDEAD , 130, "Owner died" )
+__BIONIC_ERRDEF( ENOTRECOVERABLE, 131, "State not recoverable" )
+
+#undef __BIONIC_ERRDEF
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_fdsan.h
^
|
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <android/fdsan.h>
+
+#include <errno.h>
+#include <stdatomic.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/user.h>
+
+struct FdEntry {
+ _Atomic(uint64_t) close_tag = {0};
+};
+
+struct FdTableOverflow {
+ size_t len = 0;
+ FdEntry entries[0];
+};
+
+template <size_t inline_fds>
+struct FdTableImpl {
+ constexpr FdTableImpl() {}
+
+ uint32_t version = 0; // currently 0, and hopefully it'll stay that way.
+ _Atomic(android_fdsan_error_level) error_level = {ANDROID_FDSAN_ERROR_LEVEL_DISABLED};
+
+ FdEntry entries[inline_fds];
+ _Atomic(FdTableOverflow*) overflow = {nullptr};
+
+ FdEntry* at(size_t idx);
+};
+
+using FdTable = FdTableImpl<128>;
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_fortify.h
^
|
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <poll.h> // For struct pollfd.
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/select.h> // For struct fd_set.
+
+#include <async_safe/log.h>
+
+static inline __noreturn void __fortify_fatal(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ async_safe_fatal_va_list("FORTIFY", fmt, args);
+ va_end(args);
+ abort();
+}
+
+//
+// Common helpers.
+//
+
+static inline void __check_fd_set(const char* fn, int fd, size_t set_size) {
+ if (__predict_false(fd < 0)) {
+ __fortify_fatal("%s: file descriptor %d < 0", fn, fd);
+ }
+ if (__predict_false(fd >= FD_SETSIZE)) {
+ __fortify_fatal("%s: file descriptor %d >= FD_SETSIZE %zu", fn, fd, FD_SETSIZE);
+ }
+ if (__predict_false(set_size < sizeof(fd_set))) {
+ __fortify_fatal("%s: set size %zu is too small to be an fd_set", fn, set_size);
+ }
+}
+
+static inline void __check_pollfd_array(const char* fn, size_t fds_size, nfds_t fd_count) {
+ size_t pollfd_array_length = fds_size / sizeof(pollfd);
+ if (__predict_false(pollfd_array_length < fd_count)) {
+ __fortify_fatal("%s: %zu-element pollfd array too small for %u fds",
+ fn, pollfd_array_length, fd_count);
+ }
+}
+
+static inline void __check_count(const char* fn, const char* identifier, size_t value) {
+ if (__predict_false(value > SSIZE_MAX)) {
+ __fortify_fatal("%s: %s %zu > SSIZE_MAX", fn, identifier, value);
+ }
+}
+
+static inline void __check_buffer_access(const char* fn, const char* action,
+ size_t claim, size_t actual) {
+ if (__predict_false(claim > actual)) {
+ __fortify_fatal("%s: prevented %zu-byte %s %zu-byte buffer", fn, claim, action, actual);
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_futex.h
^
|
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _BIONIC_FUTEX_H
+#define _BIONIC_FUTEX_H
+
+#include <errno.h>
+#include <linux/futex.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/cdefs.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+struct timespec;
+
+static inline int __futex(volatile void* ftx, int op, int value,
+ const timespec* timeout, int bitset) {
+ // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
+ int saved_errno = errno;
+ int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);
+ if ((result == -1)) {
+ result = -errno;
+ errno = saved_errno;
+ }
+ return result;
+}
+
+static inline int __futex_wake(volatile void* ftx, int count) {
+ return __futex(ftx, FUTEX_WAKE, count, nullptr, 0);
+}
+
+static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {
+ return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, nullptr, 0);
+}
+
+static inline int __futex_wait(volatile void* ftx, int value, const timespec* timeout) {
+ return __futex(ftx, FUTEX_WAIT, value, timeout, 0);
+}
+
+static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value) {
+ return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value, nullptr,
+ FUTEX_BITSET_MATCH_ANY);
+}
+
+__LIBC_HIDDEN__ int __futex_wait_ex(volatile void* ftx, bool shared, int value,
+ bool use_realtime_clock, const timespec* abs_timeout);
+
+static inline int __futex_pi_unlock(volatile void* ftx, bool shared) {
+ return __futex(ftx, shared ? FUTEX_UNLOCK_PI : FUTEX_UNLOCK_PI_PRIVATE, 0, nullptr, 0);
+}
+
+__LIBC_HIDDEN__ int __futex_pi_lock_ex(volatile void* ftx, bool shared, bool use_realtime_clock,
+ const timespec* abs_timeout);
+
+#endif /* _BIONIC_FUTEX_H */
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_globals.h
^
|
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_BIONIC_GLOBALS_H
+#define _PRIVATE_BIONIC_GLOBALS_H
+
+#include <stdatomic.h>
+#include <sys/cdefs.h>
+#include <link.h>
+#include <pthread.h>
+
+#include "private/bionic_allocator.h"
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_fdsan.h"
+#include "private/bionic_malloc_dispatch.h"
+#include "private/bionic_vdso.h"
+#include "private/WriteProtected.h"
+
+struct libc_globals {
+ vdso_entry vdso[VDSO_END];
+ long setjmp_cookie;
+
+ // In order to allow a complete switch between dispatch tables without
+ // the need for copying each function by function in the structure,
+ // use a single atomic pointer to switch.
+ // The current_dispatch_table pointer can only ever be set to a complete
+ // table. Any dispatch table that is pointed to by current_dispatch_table
+ // cannot be modified after that. If the pointer changes in the future,
+ // the old pointer must always stay valid.
+ // The malloc_dispatch_table is modified by malloc debug, malloc hooks,
+ // and heaprofd. Only one of these modes can be active at any given time.
+ _Atomic(const MallocDispatch*) current_dispatch_table;
+ // This pointer is only used by the allocation limit code when both a
+ // limit is enabled and some other hook is enabled at the same time.
+ _Atomic(const MallocDispatch*) default_dispatch_table;
+ MallocDispatch malloc_dispatch_table;
+};
+
+__LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals;
+
+struct abort_msg_t;
+
+// Globals shared between the dynamic linker and libc.so.
+struct libc_shared_globals {
+ // Construct the shared globals using a constexpr constructor to ensure that
+ // the object doesn't need dynamic initialization. The object is accessed
+ // before the dynamic linker has relocated itself.
+ constexpr libc_shared_globals() {}
+
+ FdTable fd_table;
+
+ // When the linker is invoked on a binary (e.g. `linker64 /system/bin/date`),
+ // record the number of arguments passed to the linker itself rather than to
+ // the program it's loading. Typically 0, sometimes 1.
+ int initial_linker_arg_count = 0;
+
+ ElfW(auxv_t)* auxv = nullptr;
+
+ pthread_mutex_t abort_msg_lock = PTHREAD_MUTEX_INITIALIZER;
+ abort_msg_t* abort_msg = nullptr;
+
+ StaticTlsLayout static_tls_layout;
+ TlsModules tls_modules;
+ BionicAllocator tls_allocator;
+
+ // Values passed from the linker to libc.so.
+ const char* init_progname = nullptr;
+ char** init_environ = nullptr;
+};
+
+__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
+__LIBC_HIDDEN__ void __libc_init_fdsan();
+
+__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals);
+__LIBC_HIDDEN__ void __libc_init_setjmp_cookie(libc_globals* globals);
+__LIBC_HIDDEN__ void __libc_init_vdso(libc_globals* globals);
+
+#if defined(__i386__)
+__LIBC_HIDDEN__ extern void* __libc_sysinfo;
+__LIBC_HIDDEN__ void __libc_int0x80();
+__LIBC_HIDDEN__ void __libc_init_sysinfo();
+#endif
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_ieee.h
^
|
@@ -0,0 +1,118 @@
+/* $OpenBSD: ieee.h,v 1.4 2011/11/08 17:06:51 deraadt Exp $ */
+/* $NetBSD: ieee.h,v 1.2 2001/02/21 17:43:50 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ieee.h 8.1 (Berkeley) 6/11/93
+ */
+
+#ifndef _MACHINE_IEEE_H_
+#define _MACHINE_IEEE_H_
+
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+#define SNG_EXPBITS 8
+#define SNG_FRACBITS 23
+
+#define SNG_EXP_INFNAN 255
+#define SNG_EXP_BIAS 127
+
+struct ieee_single {
+ unsigned sng_frac:23;
+ unsigned sng_exp:8;
+ unsigned sng_sign:1;
+};
+
+#define DBL_EXPBITS 11
+#define DBL_FRACHBITS 20
+#define DBL_FRACLBITS 32
+#define DBL_FRACBITS 52
+
+#define DBL_EXP_INFNAN 2047
+#define DBL_EXP_BIAS 1023
+
+struct ieee_double {
+ unsigned dbl_fracl;
+ unsigned dbl_frach:20;
+ unsigned dbl_exp:11;
+ unsigned dbl_sign:1;
+};
+
+#if defined(__LP64__)
+
+/* 64-bit Android uses ld128 long doubles. */
+
+#define EXT_EXPBITS 15
+#define EXT_FRACHBITS 16
+#define EXT_FRACHMBITS 32
+#define EXT_FRACLMBITS 32
+#define EXT_FRACLBITS 32
+#define EXT_FRACBITS 112
+
+#define EXT_EXP_INFNAN 32767
+#define EXT_EXP_BIAS 16383
+
+#define EXT_IMPLICIT_NBIT
+
+#define EXT_TO_ARRAY32(p, a) do { \
+ (a)[0] = (uint32_t)(p)->ext_fracl; \
+ (a)[1] = (uint32_t)(p)->ext_fraclm; \
+ (a)[2] = (uint32_t)(p)->ext_frachm; \
+ (a)[3] = (uint32_t)(p)->ext_frach; \
+} while(0)
+
+struct ieee_ext {
+ unsigned ext_fracl;
+ unsigned ext_fraclm;
+ unsigned ext_frachm;
+ unsigned ext_frach:16;
+ unsigned ext_exp:15;
+ unsigned ext_sign:1;
+};
+
+#endif
+
+__END_DECLS
+
+#endif /* _MACHINE_IEEE_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_inline_raise.h
^
|
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// An inline version of pthread_sigqueue(pthread_self(), ...), to reduce the number of
+// uninteresting stack frames at the top of a crash.
+static inline __always_inline void inline_raise(int sig, void* value = nullptr) {
+ // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
+ // http://b/37769298
+ pid_t pid = syscall(__NR_getpid);
+ pid_t tid = syscall(__NR_gettid);
+ siginfo_t info = {};
+ info.si_code = SI_QUEUE;
+ info.si_pid = pid;
+ info.si_uid = getuid();
+ info.si_value.sival_ptr = value;
+
+#if defined(__arm__)
+ register long r0 __asm__("r0") = pid;
+ register long r1 __asm__("r1") = tid;
+ register long r2 __asm__("r2") = sig;
+ register long r3 __asm__("r3") = reinterpret_cast<long>(&info);
+ register long r7 __asm__("r7") = __NR_rt_tgsigqueueinfo;
+ __asm__("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r7) : "memory");
+#elif defined(__aarch64__)
+ register long x0 __asm__("x0") = pid;
+ register long x1 __asm__("x1") = tid;
+ register long x2 __asm__("x2") = sig;
+ register long x3 __asm__("x3") = reinterpret_cast<long>(&info);
+ register long x8 __asm__("x8") = __NR_rt_tgsigqueueinfo;
+ __asm__("svc #0" : "=r"(x0) : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
+#else
+ syscall(__NR_rt_tgsigqueueinfo, pid, tid, sig, &info);
+#endif
+}
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_lock.h
^
|
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdatomic.h>
+#include "private/bionic_futex.h"
+#include "private/bionic_macros.h"
+
+// Lock is used in places like pthread_rwlock_t, which can be initialized without calling
+// an initialization function. So make sure Lock can be initialized by setting its memory to 0.
+class Lock {
+ private:
+ enum LockState {
+ Unlocked = 0,
+ LockedWithoutWaiter,
+ LockedWithWaiter,
+ };
+ _Atomic(LockState) state;
+ bool process_shared;
+
+ public:
+ void init(bool process_shared) {
+ atomic_init(&state, Unlocked);
+ this->process_shared = process_shared;
+ }
+
+ bool trylock() {
+ LockState old_state = Unlocked;
+ return (atomic_compare_exchange_strong_explicit(&state, &old_state,
+ LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed));
+ }
+
+ void lock() {
+ LockState old_state = Unlocked;
+ if ((atomic_compare_exchange_strong_explicit(&state, &old_state,
+ LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed))) {
+ return;
+ }
+ while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
+ // TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
+ __futex_wait_ex(&state, process_shared, LockedWithWaiter);
+ }
+ return;
+ }
+
+ void unlock() {
+ bool shared = process_shared; /* cache to local variable */
+ if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) {
+ __futex_wake_ex(&state, shared, 1);
+ }
+ }
+};
+
+class LockGuard {
+ public:
+ explicit LockGuard(Lock& lock) : lock_(lock) {
+ lock_.lock();
+ }
+ ~LockGuard() {
+ lock_.unlock();
+ }
+
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(LockGuard);
+
+ private:
+ Lock& lock_;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_macros.h
^
|
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#define BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+
+#define BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName() = delete; \
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+#define BIONIC_ROUND_UP_POWER_OF_2(value) \
+ ((sizeof(value) == 8) \
+ ? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
+ : (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
+
+static constexpr uintptr_t align_down(uintptr_t p, size_t align) {
+ return p & ~(align - 1);
+}
+
+static constexpr uintptr_t align_up(uintptr_t p, size_t align) {
+ return (p + align - 1) & ~(align - 1);
+}
+
+template <typename T>
+static inline T* align_down(T* p, size_t align) {
+ return reinterpret_cast<T*>(align_down(reinterpret_cast<uintptr_t>(p), align));
+}
+
+template <typename T>
+static inline T* align_up(T* p, size_t align) {
+ return reinterpret_cast<T*>(align_up(reinterpret_cast<uintptr_t>(p), align));
+}
+
+#if defined(__arm__)
+// Do not emit anything for arm, clang does not allow emiting an arm unwind
+// directive.
+// #define BIONIC_STOP_UNWIND asm volatile(".cantunwind")
+#define BIONIC_STOP_UNWIND
+#elif defined(__aarch64__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined x30")
+#elif defined(__i386__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%eip")
+#elif defined(__x86_64__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%rip")
+#elif defined (__mips__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined $ra")
+#endif
+
+// The arraysize(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example. If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that arraysize() doesn't accept any array of an
+// anonymous type or a type defined inside a function.
+//
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
+// Used to inform clang's -Wimplicit-fallthrough that a fallthrough is intended. There's no way to
+// silence (or enable, apparently) -Wimplicit-fallthrough in C yet.
+#ifdef __cplusplus
+#define __BIONIC_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define __BIONIC_FALLTHROUGH
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_malloc.h
^
|
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+// Structures for android_mallopt.
+
+typedef struct {
+ // Pointer to the buffer allocated by a call to M_GET_MALLOC_LEAK_INFO.
+ uint8_t* buffer;
+ // The size of the "info" buffer.
+ size_t overall_size;
+ // The size of a single entry.
+ size_t info_size;
+ // The sum of all allocations that have been tracked. Does not include
+ // any heap overhead.
+ size_t total_memory;
+ // The maximum number of backtrace entries.
+ size_t backtrace_size;
+} android_mallopt_leak_info_t;
+
+// Opcodes for android_mallopt.
+
+enum {
+ // Marks the calling process as a profileable zygote child, possibly
+ // initializing profiling infrastructure.
+ M_INIT_ZYGOTE_CHILD_PROFILING = 1,
+#define M_INIT_ZYGOTE_CHILD_PROFILING M_INIT_ZYGOTE_CHILD_PROFILING
+ M_RESET_HOOKS = 2,
+#define M_RESET_HOOKS M_RESET_HOOKS
+ // Set an upper bound on the total size in bytes of all allocations made
+ // using the memory allocation APIs.
+ // arg = size_t*
+ // arg_size = sizeof(size_t)
+ M_SET_ALLOCATION_LIMIT_BYTES = 3,
+#define M_SET_ALLOCATION_LIMIT_BYTES M_SET_ALLOCATION_LIMIT_BYTES
+ // Called after the zygote forks to indicate this is a child.
+ M_SET_ZYGOTE_CHILD = 4,
+#define M_SET_ZYGOTE_CHILD M_SET_ZYGOTE_CHILD
+
+ // Options to dump backtraces of allocations. These options only
+ // work when malloc debug has been enabled.
+
+ // Writes the backtrace information of all current allocations to a file.
+ // NOTE: arg_size has to be sizeof(FILE*) because FILE is an opaque type.
+ // arg = FILE*
+ // arg_size = sizeof(FILE*)
+ M_WRITE_MALLOC_LEAK_INFO_TO_FILE = 5,
+#define M_WRITE_MALLOC_LEAK_INFO_TO_FILE M_WRITE_MALLOC_LEAK_INFO_TO_FILE
+ // Get information about the backtraces of all
+ // arg = android_mallopt_leak_info_t*
+ // arg_size = sizeof(android_mallopt_leak_info_t)
+ M_GET_MALLOC_LEAK_INFO = 6,
+#define M_GET_MALLOC_LEAK_INFO M_GET_MALLOC_LEAK_INFO
+ // Free the memory allocated and returned by M_GET_MALLOC_LEAK_INFO.
+ // arg = android_mallopt_leak_info_t*
+ // arg_size = sizeof(android_mallopt_leak_info_t)
+ M_FREE_MALLOC_LEAK_INFO = 7,
+#define M_FREE_MALLOC_LEAK_INFO M_FREE_MALLOC_LEAK_INFO
+};
+
+// Manipulates bionic-specific handling of memory allocation APIs such as
+// malloc. Only for use by the Android platform itself.
+//
+// On success, returns true. On failure, returns false and sets errno.
+extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size);
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_malloc_dispatch.h
^
|
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_BIONIC_MALLOC_DISPATCH_H
+#define _PRIVATE_BIONIC_MALLOC_DISPATCH_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <private/bionic_config.h>
+
+// Entry in malloc dispatch table.
+typedef void* (*MallocCalloc)(size_t, size_t);
+typedef void (*MallocFree)(void*);
+typedef struct mallinfo (*MallocMallinfo)();
+typedef void* (*MallocMalloc)(size_t);
+typedef int (*MallocMallocInfo)(int, FILE*);
+typedef size_t (*MallocMallocUsableSize)(const void*);
+typedef void* (*MallocMemalign)(size_t, size_t);
+typedef int (*MallocPosixMemalign)(void**, size_t, size_t);
+typedef void* (*MallocRealloc)(void*, size_t);
+typedef int (*MallocIterate)(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
+typedef void (*MallocMallocDisable)();
+typedef void (*MallocMallocEnable)();
+typedef int (*MallocMallopt)(int, int);
+typedef void* (*MallocAlignedAlloc)(size_t, size_t);
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+typedef void* (*MallocPvalloc)(size_t);
+typedef void* (*MallocValloc)(size_t);
+#endif
+
+struct MallocDispatch {
+ MallocCalloc calloc;
+ MallocFree free;
+ MallocMallinfo mallinfo;
+ MallocMalloc malloc;
+ MallocMallocUsableSize malloc_usable_size;
+ MallocMemalign memalign;
+ MallocPosixMemalign posix_memalign;
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+ MallocPvalloc pvalloc;
+#endif
+ MallocRealloc realloc;
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+ MallocValloc valloc;
+#endif
+ MallocIterate iterate;
+ MallocMallocDisable malloc_disable;
+ MallocMallocEnable malloc_enable;
+ MallocMallopt mallopt;
+ MallocAlignedAlloc aligned_alloc;
+ MallocMallocInfo malloc_info;
+} __attribute__((aligned(32)));
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_mbstate.h
^
|
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BIONIC_MBSTATE_H
+#define _BIONIC_MBSTATE_H
+
+#include <errno.h>
+#include <wchar.h>
+
+__BEGIN_DECLS
+
+/*
+ * These return values are specified by POSIX for multibyte conversion
+ * functions.
+ */
+#define __MB_ERR_ILLEGAL_SEQUENCE static_cast<size_t>(-1)
+#define __MB_ERR_INCOMPLETE_SEQUENCE static_cast<size_t>(-2)
+
+#define __MB_IS_ERR(rv) (rv == __MB_ERR_ILLEGAL_SEQUENCE || \
+ rv == __MB_ERR_INCOMPLETE_SEQUENCE)
+
+static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) {
+ return
+ (ps->__seq[2] != 0) ? 3 :
+ (ps->__seq[1] != 0) ? 2 :
+ (ps->__seq[0] != 0) ? 1 : 0;
+}
+
+static inline void mbstate_set_byte(mbstate_t* ps, int i, char byte) {
+ ps->__seq[i] = static_cast<uint8_t>(byte);
+}
+
+static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
+ return ps->__seq[n];
+}
+
+static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
+ errno = _errno;
+ *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
+ return __MB_ERR_ILLEGAL_SEQUENCE;
+}
+
+static inline __wur size_t mbstate_reset_and_return(int _return, mbstate_t* ps) {
+ *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
+ return _return;
+}
+
+__END_DECLS
+
+#endif // _BIONIC_MBSTATE_H
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_page.h
^
|
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_PAGE_H_
+#define _BIONIC_PAGE_H_
+
+// Get PAGE_SIZE and PAGE_MASK.
+#include <sys/user.h>
+
+// Returns the address of the page containing address 'x'.
+#define PAGE_START(x) ((x) & PAGE_MASK)
+
+// Returns the offset of address 'x' in its page.
+#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
+
+// Returns the address of the next page after address 'x', unless 'x' is
+// itself at the start of a page.
+#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
+
+#endif // _BIONIC_PAGE_H_
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_prctl.h
^
|
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BIONIC_PRCTL_H
+#define BIONIC_PRCTL_H
+
+#include <sys/prctl.h>
+
+// This is only supported by Android kernels, so it's not in the uapi headers.
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
+
+#endif // BIONIC_PRCTL_H
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_sdk_version.h
^
|
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_SDK_VERSION_H_
+#define _BIONIC_SDK_VERSION_H_
+
+#include <stdint.h>
+
+uint32_t bionic_get_application_target_sdk_version();
+
+#endif // _BIONIC_SDK_VERSION_H_
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_sigdefs.h
^
|
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * this header is used to define signal constants and names;
+ * it might be included several times
+ */
+
+#ifndef __BIONIC_SIGDEF
+#error __BIONIC_SIGDEF not defined
+#endif
+
+__BIONIC_SIGDEF(SIGHUP, "Hangup")
+__BIONIC_SIGDEF(SIGINT, "Interrupt")
+__BIONIC_SIGDEF(SIGQUIT, "Quit")
+__BIONIC_SIGDEF(SIGILL, "Illegal instruction")
+__BIONIC_SIGDEF(SIGTRAP, "Trap")
+__BIONIC_SIGDEF(SIGABRT, "Aborted")
+#ifdef SIGEMT
+__BIONIC_SIGDEF(SIGEMT, "EMT")
+#endif
+__BIONIC_SIGDEF(SIGFPE, "Floating point exception")
+__BIONIC_SIGDEF(SIGKILL, "Killed")
+__BIONIC_SIGDEF(SIGBUS, "Bus error")
+__BIONIC_SIGDEF(SIGSEGV, "Segmentation fault")
+__BIONIC_SIGDEF(SIGPIPE, "Broken pipe")
+__BIONIC_SIGDEF(SIGALRM, "Alarm clock")
+__BIONIC_SIGDEF(SIGTERM, "Terminated")
+__BIONIC_SIGDEF(SIGUSR1, "User signal 1")
+__BIONIC_SIGDEF(SIGUSR2, "User signal 2")
+__BIONIC_SIGDEF(SIGCHLD, "Child exited")
+__BIONIC_SIGDEF(SIGPWR, "Power failure")
+__BIONIC_SIGDEF(SIGWINCH, "Window size changed")
+__BIONIC_SIGDEF(SIGURG, "Urgent I/O condition")
+__BIONIC_SIGDEF(SIGIO, "I/O possible")
+__BIONIC_SIGDEF(SIGSTOP, "Stopped (signal)")
+__BIONIC_SIGDEF(SIGTSTP, "Stopped")
+__BIONIC_SIGDEF(SIGCONT, "Continue")
+__BIONIC_SIGDEF(SIGTTIN, "Stopped (tty input)")
+__BIONIC_SIGDEF(SIGTTOU, "Stopped (tty output)")
+__BIONIC_SIGDEF(SIGVTALRM, "Virtual timer expired")
+__BIONIC_SIGDEF(SIGPROF, "Profiling timer expired")
+__BIONIC_SIGDEF(SIGXCPU, "CPU time limit exceeded")
+__BIONIC_SIGDEF(SIGXFSZ, "File size limit exceeded")
+#if defined(SIGSTKFLT)
+__BIONIC_SIGDEF(SIGSTKFLT, "Stack fault")
+#endif
+__BIONIC_SIGDEF(SIGSYS, "Bad system call")
+
+#undef __BIONIC_SIGDEF
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_ssp.h
^
|
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_SSP_H
+#define _PRIVATE_SSP_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* GCC uses this on ARM and MIPS; we use it on x86 to set the guard in TLS. */
+extern uintptr_t __stack_chk_guard;
+
+/* GCC calls this if a stack guard check fails. */
+extern void __stack_chk_fail();
+
+__END_DECLS
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_string_utils.h
^
|
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_STRING_UTILS_H_
+#define _BIONIC_STRING_UTILS_H_
+
+#include <string.h>
+
+static inline bool ends_with(const char* s1, const char* s2) {
+ size_t s1_length = strlen(s1);
+ size_t s2_length = strlen(s2);
+ if (s2_length > s1_length) {
+ return false;
+ }
+ return memcmp(s1 + (s1_length - s2_length), s2, s2_length) == 0;
+}
+
+#endif // _BIONIC_STRING_UTILS_H_
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_systrace.h
^
|
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/cdefs-android.h>
+#include "bionic_macros.h"
+
+// Tracing class for bionic. To begin a trace at a specified point:
+// ScopedTrace("Trace message");
+// The trace will end when the contructor goes out of scope.
+
+class __LIBC_HIDDEN__ ScopedTrace {
+ public:
+ explicit ScopedTrace(const char* message) {};
+ ~ScopedTrace() {};
+
+ void End() {};
+ private:
+ bool called_end_;
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
+};
+
+static inline void bionic_trace_begin(const char* message) {};
+static inline void bionic_trace_end() {};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_time_conversions.h
^
|
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BIONIC_TIME_CONVERSIONS_H
+#define _BIONIC_TIME_CONVERSIONS_H
+
+#include <errno.h>
+#include <time.h>
+#include <sys/cdefs.h>
+
+#include "private/bionic_constants.h"
+
+__BEGIN_DECLS
+
+__LIBC_HIDDEN__ bool timespec_from_timeval(timespec& ts, const timeval& tv);
+__LIBC_HIDDEN__ void timespec_from_ms(timespec& ts, const int ms);
+
+__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
+
+__LIBC_HIDDEN__ void monotonic_time_from_realtime_time(timespec& monotonic_time,
+ const timespec& realtime_time);
+
+__END_DECLS
+
+static inline int check_timespec(const timespec* ts, bool null_allowed) {
+ if (null_allowed && ts == nullptr) {
+ return 0;
+ }
+ // glibc just segfaults if you pass a null timespec.
+ // That seems a lot more likely to catch bad code than returning EINVAL.
+ if (ts->tv_nsec < 0 || ts->tv_nsec >= NS_PER_S) {
+ return EINVAL;
+ }
+ if (ts->tv_sec < 0) {
+ return ETIMEDOUT;
+ }
+ return 0;
+}
+
+#if !defined(__LP64__)
+static inline void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts, clockid_t clock) {
+ clock_gettime(clock, &abs_ts);
+ abs_ts.tv_sec += ts.tv_sec;
+ abs_ts.tv_nsec += ts.tv_nsec;
+ if (abs_ts.tv_nsec >= NS_PER_S) {
+ abs_ts.tv_nsec -= NS_PER_S;
+ abs_ts.tv_sec++;
+ }
+}
+#endif
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_tls.h
^
|
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <locale.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+
+#include "bionic_asm_tls.h"
+#include "bionic_macros.h"
+#include "__get_tls.h"
+#include "grp_pwd.h"
+
+/** WARNING WARNING WARNING
+ **
+ ** This header file is *NOT* part of the public Bionic ABI/API and should not
+ ** be used/included by user-serviceable parts of the system (e.g.
+ ** applications).
+ **/
+
+class pthread_internal_t;
+
+// This struct is small, so the linker can allocate a temporary copy on its
+// stack. It can't be combined with pthread_internal_t because:
+// - native bridge requires pthread_internal_t to have the same layout across
+// architectures, and
+// - On x86, this struct would have to be placed at the front of
+// pthread_internal_t, moving fields like `tid`.
+// - We'd like to avoid having a temporary pthread_internal_t object that
+// needs to be transferred once the final size of static TLS is known.
+struct bionic_tcb {
+ void* raw_slots_storage[BIONIC_TLS_SLOTS];
+
+ // Return a reference to a slot given its TP-relative TLS_SLOT_xxx index.
+ // The thread pointer (i.e. __get_tls()) points at &tls_slot(0).
+ void*& tls_slot(size_t tpindex) {
+ return raw_slots_storage[tpindex - MIN_TLS_SLOT];
+ }
+
+ // Initialize the main thread's final object using its bootstrap object.
+ void copy_from_bootstrap(const bionic_tcb* boot) {
+ // Copy everything. Problematic slots will be reinitialized.
+ *this = *boot;
+ }
+
+ pthread_internal_t* thread() {
+ return static_cast<pthread_internal_t*>(tls_slot(TLS_SLOT_THREAD_ID));
+ }
+};
+
+/*
+ * Bionic uses some pthread keys internally. All pthread keys used internally
+ * should be created in constructors, except for keys that may be used in or
+ * before constructors.
+ *
+ * We need to manually maintain the count of pthread keys used internally, but
+ * pthread_test should fail if we forget.
+ *
+ * These are the pthread keys currently used internally by libc:
+ * _res_key libc (constructor in BSD code)
+ */
+
+#define LIBC_PTHREAD_KEY_RESERVED_COUNT 1
+
+/* Internally, jemalloc uses a single key for per thread data. */
+#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 1
+#define BIONIC_PTHREAD_KEY_RESERVED_COUNT (LIBC_PTHREAD_KEY_RESERVED_COUNT + JEMALLOC_PTHREAD_KEY_RESERVED_COUNT)
+
+/*
+ * Maximum number of pthread keys allocated.
+ * This includes pthread keys used internally and externally.
+ */
+#define BIONIC_PTHREAD_KEY_COUNT (BIONIC_PTHREAD_KEY_RESERVED_COUNT + PTHREAD_KEYS_MAX)
+
+class pthread_key_data_t {
+ public:
+ uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below.
+ void* data;
+};
+
+// ~3 pages. This struct is allocated as static TLS memory (i.e. at a fixed
+// offset from the thread pointer).
+struct bionic_tls {
+ pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
+
+ locale_t locale;
+
+ char basename_buf[MAXPATHLEN];
+ char dirname_buf[MAXPATHLEN];
+
+ mntent mntent_buf;
+ char mntent_strings[BUFSIZ];
+
+ char ptsname_buf[32];
+ char ttyname_buf[64];
+
+ char strerror_buf[NL_TEXTMAX];
+ char strsignal_buf[NL_TEXTMAX];
+
+ group_state_t group;
+ passwd_state_t passwd;
+
+ // Initialize the main thread's final object using its bootstrap object.
+ void copy_from_bootstrap(const bionic_tls* boot __attribute__((unused))) {
+ // Nothing in bionic_tls needs to be preserved in the transition to the
+ // final TLS objects, so don't copy anything.
+ }
+};
+
+class KernelArgumentBlock;
+extern "C" void __libc_init_main_thread_early(const KernelArgumentBlock& args, bionic_tcb* temp_tcb);
+extern "C" void __libc_init_main_thread_late();
+extern "C" void __libc_init_main_thread_final();
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/bionic_vdso.h
^
|
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_BIONIC_VDSO_H
+#define _PRIVATE_BIONIC_VDSO_H
+
+#include <time.h>
+
+#if defined(__aarch64__)
+#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
+#define VDSO_CLOCK_GETRES_SYMBOL "__kernel_clock_getres"
+#define VDSO_GETTIMEOFDAY_SYMBOL "__kernel_gettimeofday"
+#define VDSO_TIME_SYMBOL "__kernel_time"
+#else
+#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
+#define VDSO_CLOCK_GETRES_SYMBOL "__vdso_clock_getres"
+#define VDSO_GETTIMEOFDAY_SYMBOL "__vdso_gettimeofday"
+#define VDSO_TIME_SYMBOL "__vdso_time"
+#endif
+
+extern "C" int __clock_gettime(int, timespec*);
+extern "C" int __clock_getres(int, timespec*);
+extern "C" int __gettimeofday(timeval*, struct timezone*);
+
+struct vdso_entry {
+ const char* name;
+ void* fn;
+};
+
+enum {
+ VDSO_CLOCK_GETTIME = 0,
+ VDSO_CLOCK_GETRES,
+ VDSO_GETTIMEOFDAY,
+ VDSO_TIME,
+ VDSO_END
+};
+
+#endif // _PRIVATE_BIONIC_VDSO_H
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/get_cpu_count_from_string.h
^
|
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+
+// Parse a string like: 0, 2-4, 6.
+static int GetCpuCountFromString(const char* s) {
+ int cpu_count = 0;
+ int last_cpu = -1;
+ while (*s != '\0') {
+ if (isdigit(*s)) {
+ int cpu = static_cast<int>(strtol(s, const_cast<char**>(&s), 10));
+ if (last_cpu != -1) {
+ cpu_count += cpu - last_cpu;
+ } else {
+ cpu_count++;
+ }
+ last_cpu = cpu;
+ } else {
+ if (*s == ',') {
+ last_cpu = -1;
+ }
+ s++;
+ }
+ }
+ return cpu_count;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/grp_pwd.h
^
|
@@ -0,0 +1,50 @@
+#pragma once
+
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <grp.h>
+#include <pwd.h>
+
+static constexpr size_t kGrpPwdBufferSize = 32;
+
+struct group_state_t {
+ group group_;
+ char* group_members_[2];
+ char group_name_buffer_[kGrpPwdBufferSize];
+ // Must be last so init_group_state can run a simple memset for the above
+ ssize_t getgrent_idx;
+};
+
+struct passwd_state_t {
+ passwd passwd_;
+ char name_buffer_[kGrpPwdBufferSize];
+ char dir_buffer_[kGrpPwdBufferSize];
+ char sh_buffer_[kGrpPwdBufferSize];
+ ssize_t getpwent_idx;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/icu.h
^
|
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_ICU_H
+#define _PRIVATE_ICU_H
+
+#include <stdint.h>
+#include <wchar.h>
+
+typedef int8_t UBool;
+#define FALSE 0
+#define TRUE 1
+
+typedef int32_t UChar32;
+
+enum UProperty {
+ UCHAR_ALPHABETIC = 0,
+ UCHAR_DEFAULT_IGNORABLE_CODE_POINT = 5,
+ UCHAR_LOWERCASE = 22,
+ UCHAR_POSIX_ALNUM = 44,
+ UCHAR_POSIX_BLANK = 45,
+ UCHAR_POSIX_GRAPH = 46,
+ UCHAR_POSIX_PRINT = 47,
+ UCHAR_POSIX_XDIGIT = 48,
+ UCHAR_UPPERCASE = 30,
+ UCHAR_WHITE_SPACE = 31,
+ UCHAR_EAST_ASIAN_WIDTH = 0x1004,
+ UCHAR_HANGUL_SYLLABLE_TYPE = 0x100b,
+};
+
+enum UCharCategory {
+ U_NON_SPACING_MARK = 6,
+ U_ENCLOSING_MARK = 7,
+ U_CONTROL_CHAR = 15,
+ U_FORMAT_CHAR = 16,
+};
+
+enum UEastAsianWidth {
+ U_EA_NEUTRAL,
+ U_EA_AMBIGUOUS,
+ U_EA_HALFWIDTH,
+ U_EA_FULLWIDTH,
+ U_EA_NARROW,
+ U_EA_WIDE,
+};
+
+enum UHangulSyllableType {
+ U_HST_NOT_APPLICABLE,
+ U_HST_LEADING_JAMO,
+ U_HST_VOWEL_JAMO,
+ U_HST_TRAILING_JAMO,
+ U_HST_LV_SYLLABLE,
+ U_HST_LVT_SYLLABLE,
+};
+
+int8_t __icu_charType(wint_t wc);
+int32_t __icu_getIntPropertyValue(wint_t wc, UProperty property);
+bool __icu_hasBinaryProperty(wint_t wc, UProperty property, int (*fallback)(int));
+
+void* __find_icu_symbol(const char* symbol_name);
+
+#endif // _PRIVATE_ICU_H
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/kernel_sigset_t.h
^
|
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBC_PRIVATE_KERNEL_SIGSET_T_H_
+#define LIBC_PRIVATE_KERNEL_SIGSET_T_H_
+
+#include <signal.h>
+
+// Our sigset_t is wrong for ARM and x86. It's 32-bit but the kernel expects 64 bits.
+// This means we can't support real-time signals correctly until we can change the ABI.
+// In the meantime, we can use this union to pass an appropriately-sized block of memory
+// to the kernel, at the cost of not being able to refer to real-time signals.
+union kernel_sigset_t {
+ kernel_sigset_t() {
+ clear();
+ }
+
+ kernel_sigset_t(const sigset_t* value) {
+ clear();
+ set(value);
+ }
+
+ void clear() {
+ __builtin_memset(this, 0, sizeof(*this));
+ }
+
+ void set(const sigset_t* value) {
+ bionic = *value;
+ }
+
+ sigset_t* get() {
+ return &bionic;
+ }
+
+ sigset_t bionic;
+#ifndef __mips__
+ uint32_t kernel[2];
+#endif
+};
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/linker_native_bridge.h
^
|
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+extern "C" void __linker_reserve_bionic_tls_in_static_tls();
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/sigrtmin.h
^
|
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#include <signal.h>
+
+#include "bionic_macros.h"
+
+// Realtime signals reserved for internal use:
+// 32 (__SIGRTMIN + 0) POSIX timers
+// 33 (__SIGRTMIN + 1) libbacktrace
+// 34 (__SIGRTMIN + 2) libcore
+// 35 (__SIGRTMIN + 3) debuggerd -b
+// 36 (__SIGRTMIN + 4) heapprofd
+// 37 (__SIGRTMIN + 5) coverage (libprofile-extras)
+//
+// If you change this, also change __ndk_legacy___libc_current_sigrtmin
+// in <android/legacy_signal_inlines.h> to match.
+
+#define __SIGRT_RESERVED 6
+static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
+ int (*block)(sigset64_t*, int);
+ int (*unblock)(sigset64_t*, int);
+ switch (how) {
+ case SIG_BLOCK:
+ __BIONIC_FALLTHROUGH;
+ case SIG_SETMASK:
+ block = sigaddset64;
+ unblock = sigdelset64;
+ break;
+
+ case SIG_UNBLOCK:
+ block = sigdelset64;
+ unblock = sigaddset64;
+ break;
+ }
+
+ // The POSIX timer signal must be blocked.
+ block(&sigset, __SIGRTMIN + 0);
+
+ // Everything else must remain unblocked.
+ unblock(&sigset, __SIGRTMIN + 1);
+ unblock(&sigset, __SIGRTMIN + 2);
+ unblock(&sigset, __SIGRTMIN + 3);
+ unblock(&sigset, __SIGRTMIN + 4);
+ unblock(&sigset, __SIGRTMIN + 5);
+ return sigset;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/bionic/libc/private/thread_private.h
^
|
@@ -0,0 +1,36 @@
+/* $OpenBSD: thread_private.h,v 1.18 2006/02/22 07:16:31 otto Exp $ */
+
+/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
+
+#pragma once
+
+#include <pthread.h>
+
+__BEGIN_DECLS
+
+/*
+ * This file defines the thread library interface to libc. Thread
+ * libraries must implement the functions described here for proper
+ * inter-operation with libc. libc contains weak versions of the
+ * described functions for operation in a non-threaded environment.
+ */
+
+#define __MUTEX_NAME(name) __CONCAT(__libc_mutex_,name)
+#define _THREAD_PRIVATE_MUTEX(name) static pthread_mutex_t __MUTEX_NAME(name) = PTHREAD_MUTEX_INITIALIZER
+#define _THREAD_PRIVATE_MUTEX_LOCK(name) pthread_mutex_lock(&__MUTEX_NAME(name))
+#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) pthread_mutex_unlock(&__MUTEX_NAME(name))
+
+/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
+#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
+#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
+
+__LIBC_HIDDEN__ void _thread_arc4_lock(void);
+__LIBC_HIDDEN__ void _thread_arc4_unlock(void);
+
+#define _ARC4_LOCK() _thread_arc4_lock()
+#define _ARC4_UNLOCK() _thread_arc4_unlock()
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+extern volatile sig_atomic_t _rs_forked;
+
+__END_DECLS
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/dlfcn.cpp
^
|
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker.h"
+#include "linker_cfi.h"
+#include "linker_globals.h"
+#include "linker_dlwarning.h"
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <android/api-level.h>
+
+#include <bionic/pthread_internal.h>
+#include "private/bionic_globals.h"
+#include "private/bionic_tls.h"
+#include "private/ScopedPthreadMutexLocker.h"
+
+#define __LINKER_PUBLIC__ __attribute__((visibility("default")))
+
+extern "C" {
+
+android_namespace_t* __loader_android_create_namespace(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ android_namespace_t* parent_namespace,
+ const void* caller_addr) __LINKER_PUBLIC__;
+void* __loader_android_dlopen_ext(const char* filename,
+ int flags,
+ const android_dlextinfo* extinfo,
+ const void* caller_addr) __LINKER_PUBLIC__;
+void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*)) __LINKER_PUBLIC__;
+int __loader_android_get_application_target_sdk_version() __LINKER_PUBLIC__;
+void __loader_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) __LINKER_PUBLIC__;
+android_namespace_t* __loader_android_get_exported_namespace(const char* name) __LINKER_PUBLIC__;
+bool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
+ const char* library_search_path) __LINKER_PUBLIC__;
+bool __loader_android_link_namespaces(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to,
+ const char* shared_libs_sonames) __LINKER_PUBLIC__;
+bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to) __LINKER_PUBLIC__;
+void __loader_android_set_application_target_sdk_version(int target) __LINKER_PUBLIC__;
+void __loader_android_update_LD_LIBRARY_PATH(const char* ld_library_path) __LINKER_PUBLIC__;
+void __loader_cfi_fail(uint64_t CallSiteTypeId,
+ void* Ptr,
+ void *DiagData,
+ void *CallerPc) __LINKER_PUBLIC__;
+int __loader_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data),
+ void* data) __LINKER_PUBLIC__;
+int __loader_dladdr(const void* addr, Dl_info* info) __LINKER_PUBLIC__;
+int __loader_dlclose(void* handle) __LINKER_PUBLIC__;
+char* __loader_dlerror() __LINKER_PUBLIC__;
+void* __loader_dlopen(const char* filename, int flags, const void* caller_addr) __LINKER_PUBLIC__;
+void* __loader_dlsym(void* handle, const char* symbol, const void* caller_addr) __LINKER_PUBLIC__;
+void* __loader_dlvsym(void* handle,
+ const char* symbol,
+ const char* version,
+ const void* caller_addr) __LINKER_PUBLIC__;
+void __loader_add_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
+void __loader_remove_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
+libc_shared_globals* __loader_shared_globals() __LINKER_PUBLIC__;
+#if defined(__arm__)
+_Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_PUBLIC__;
+#endif
+}
+
+static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+static __thread char *dl_err_str;
+char __thread dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
+
+static char* __bionic_set_dlerror(char* new_value) {
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ char* old_value = __get_thread()->current_dlerror;
+ __get_thread()->current_dlerror = new_value;
+
+ if (new_value != nullptr) LD_LOG(kLogErrors, "dlerror set to \"%s\"", new_value);
+ return old_value;
+#else
+ char *old_value = dl_err_str;
+ dl_err_str = new_value;
+ return old_value;
+#endif
+}
+
+static void __bionic_format_dlerror(const char* msg, const char* detail) {
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ char* buffer = __get_thread()->dlerror_buffer;
+#else
+ char* buffer = dlerror_buffer;
+#endif
+ strlcpy(buffer, msg, __BIONIC_DLERROR_BUFFER_SIZE);
+ if (detail != nullptr) {
+ strlcat(buffer, ": ", __BIONIC_DLERROR_BUFFER_SIZE);
+ strlcat(buffer, detail, __BIONIC_DLERROR_BUFFER_SIZE);
+ }
+
+ __bionic_set_dlerror(buffer);
+}
+
+char* __loader_dlerror() {
+ char* old_value = __bionic_set_dlerror(nullptr);
+ return old_value;
+}
+
+void __loader_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ do_android_get_LD_LIBRARY_PATH(buffer, buffer_size);
+}
+
+void __loader_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ do_android_update_LD_LIBRARY_PATH(ld_library_path);
+}
+
+static void* dlopen_ext(const char* filename,
+ int flags,
+ const android_dlextinfo* extinfo,
+ const void* caller_addr) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ g_linker_logger.ResetState();
+ void* result = do_dlopen(filename, flags, extinfo, caller_addr);
+ if (result == nullptr) {
+ __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
+ return nullptr;
+ }
+ return result;
+}
+
+void* __loader_android_dlopen_ext(const char* filename,
+ int flags,
+ const android_dlextinfo* extinfo,
+ const void* caller_addr) {
+ return dlopen_ext(filename, flags, extinfo, caller_addr);
+}
+
+void* __loader_dlopen(const char* filename, int flags, const void* caller_addr) {
+ return dlopen_ext(filename, flags, nullptr, caller_addr);
+}
+
+void* dlsym_impl(void* handle, const char* symbol, const char* version, const void* caller_addr) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ g_linker_logger.ResetState();
+ void* result;
+ if (!do_dlsym(handle, symbol, version, caller_addr, &result)) {
+ __bionic_format_dlerror(linker_get_error_buffer(), nullptr);
+ return nullptr;
+ }
+
+ return result;
+}
+
+void* __loader_dlsym(void* handle, const char* symbol, const void* caller_addr) {
+ return dlsym_impl(handle, symbol, nullptr, caller_addr);
+}
+
+void* __loader_dlvsym(void* handle, const char* symbol, const char* version, const void* caller_addr) {
+ return dlsym_impl(handle, symbol, version, caller_addr);
+}
+
+int __loader_dladdr(const void* addr, Dl_info* info) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ return do_dladdr(addr, info);
+}
+
+int __loader_dlclose(void* handle) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ int result = do_dlclose(handle);
+ if (result != 0) {
+ __bionic_format_dlerror("dlclose failed", linker_get_error_buffer());
+ }
+ return result;
+}
+
+int __loader_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ return do_dl_iterate_phdr(cb, data);
+}
+
+// This function is needed by libgcc.a
+int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
+ return __loader_dl_iterate_phdr(cb, data);
+}
+
+#if defined(__arm__)
+_Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ return do_dl_unwind_find_exidx(pc, pcount);
+}
+#endif
+
+void __loader_android_set_application_target_sdk_version(int target) {
+ // lock to avoid modification in the middle of dlopen.
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ set_application_target_sdk_version(target);
+}
+
+int __loader_android_get_application_target_sdk_version() {
+ return get_application_target_sdk_version();
+}
+
+void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*)) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ get_dlwarning(obj, f);
+}
+
+bool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
+ const char* library_search_path) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ bool success = init_anonymous_namespace(shared_libs_sonames, library_search_path);
+ if (!success) {
+ __bionic_format_dlerror("android_init_anonymous_namespace failed", linker_get_error_buffer());
+ }
+
+ return success;
+}
+
+android_namespace_t* __loader_android_create_namespace(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ android_namespace_t* parent_namespace,
+ const void* caller_addr) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+
+ android_namespace_t* result = create_namespace(caller_addr,
+ name,
+ ld_library_path,
+ default_library_path,
+ type,
+ permitted_when_isolated_path,
+ parent_namespace);
+
+ if (result == nullptr) {
+ __bionic_format_dlerror("android_create_namespace failed", linker_get_error_buffer());
+ }
+
+ return result;
+}
+
+bool __loader_android_link_namespaces(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to,
+ const char* shared_libs_sonames) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+
+ bool success = link_namespaces(namespace_from, namespace_to, shared_libs_sonames);
+
+ if (!success) {
+ __bionic_format_dlerror("android_link_namespaces failed", linker_get_error_buffer());
+ }
+
+ return success;
+}
+
+bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+
+ bool success = link_namespaces_all_libs(namespace_from, namespace_to);
+
+ if (!success) {
+ __bionic_format_dlerror("android_link_namespaces_all_libs failed", linker_get_error_buffer());
+ }
+
+ return success;
+}
+
+android_namespace_t* __loader_android_get_exported_namespace(const char* name) {
+ return get_exported_namespace(name);
+}
+
+void __loader_cfi_fail(uint64_t CallSiteTypeId, void* Ptr, void *DiagData, void *CallerPc) {
+ CFIShadowWriter::CfiFail(CallSiteTypeId, Ptr, DiagData, CallerPc);
+}
+
+void __loader_add_thread_local_dtor(void* dso_handle) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ increment_dso_handle_reference_counter(dso_handle);
+}
+
+void __loader_remove_thread_local_dtor(void* dso_handle) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ decrement_dso_handle_reference_counter(dso_handle);
+}
+
+__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() {
+ static libc_shared_globals globals;
+ return &globals;
+}
+
+libc_shared_globals* __loader_shared_globals() {
+ return __libc_shared_globals();
+}
+
+static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
+static soinfo* __libdl_info = nullptr;
+
+// This is used by the dynamic linker. Every process gets these symbols for free.
+soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si) {
+ //CHECK((linker_si.flags_ & FLAG_GNU_HASH) != 0);
+
+ if (__libdl_info == nullptr) {
+ __libdl_info = new (__libdl_info_buf) soinfo(g_default_namespace, linker_path, nullptr, 0, 0);
+ __libdl_info->flags_ |= (FLAG_LINKED | FLAG_GNU_HASH);
+ __libdl_info->strtab_ = linker_si.strtab_;
+ __libdl_info->symtab_ = linker_si.symtab_;
+ __libdl_info->load_bias = linker_si.load_bias;
+ __libdl_info->phdr = linker_si.phdr;
+ __libdl_info->phnum = linker_si.phnum;
+
+ __libdl_info->gnu_nbucket_ = linker_si.gnu_nbucket_;
+ __libdl_info->gnu_maskwords_ = linker_si.gnu_maskwords_;
+ __libdl_info->gnu_shift2_ = linker_si.gnu_shift2_;
+ __libdl_info->gnu_bloom_filter_ = linker_si.gnu_bloom_filter_;
+ __libdl_info->gnu_bucket_ = linker_si.gnu_bucket_;
+ __libdl_info->gnu_chain_ = linker_si.gnu_chain_;
+
+ __libdl_info->ref_count_ = 1;
+ __libdl_info->strtab_size_ = linker_si.strtab_size_;
+ __libdl_info->local_group_root_ = __libdl_info;
+ __libdl_info->soname_ = linker_si.soname_;
+ __libdl_info->target_sdk_version_ = __ANDROID_API__;
+ __libdl_info->generate_handle();
+#if defined(__work_around_b_24465209__)
+ strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
+#endif
+ }
+
+ return __libdl_info;
+}
+
+// hybris compat
+extern "C" {
+void* android_dlopen(const char* filename, int flag) {
+ const void* caller_addr = __builtin_return_address(0);
+ return __loader_dlopen(filename, flag, caller_addr);
+}
+
+char* android_dlerror() {
+ return __loader_dlerror();
+}
+
+void* android_dlsym(void* handle, const char* symbol) {
+ const void* caller_addr = __builtin_return_address(0);
+ return __loader_dlsym(handle, symbol, caller_addr);
+}
+
+void* android_dlvsym(void* handle, const char* symbol, const char* version) {
+ const void* caller_addr = __builtin_return_address(0);
+ return __loader_dlvsym(handle, symbol, version, caller_addr);
+}
+
+int android_dladdr(const void* addr, Dl_info* info) {
+ return __loader_dladdr(addr, info);
+}
+
+int android_dlclose(void* handle) {
+ return __loader_dlclose(handle);
+}
+
+#if defined(__arm__)
+_Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
+ return __loader_dl_unwind_find_exidx(pc, pcount);
+}
+#endif
+
+int android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
+ return __loader_dl_iterate_phdr(cb, data);
+}
+
+void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
+ __loader_android_get_LD_LIBRARY_PATH(buffer, buffer_size);
+}
+
+void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
+ __loader_android_update_LD_LIBRARY_PATH(ld_library_path);
+}
+
+void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo) {
+ const void* caller_addr = __builtin_return_address(0);
+ return __loader_android_dlopen_ext(filename, flag, extinfo, caller_addr);
+}
+
+void android_set_application_target_sdk_version(uint32_t target) {
+ __loader_android_set_application_target_sdk_version(target);
+}
+
+int android_get_application_target_sdk_version() {
+ return __loader_android_get_application_target_sdk_version();
+}
+
+bool android_init_anonymous_namespace(const char* shared_libs_sonames,
+ const char* library_search_path) {
+ return __loader_android_init_anonymous_namespace(shared_libs_sonames, library_search_path);
+}
+
+struct android_namespace_t* android_create_namespace(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ struct android_namespace_t* parent) {
+ const void* caller_addr = __builtin_return_address(0);
+ return __loader_android_create_namespace(name,
+ ld_library_path,
+ default_library_path,
+ type,
+ permitted_when_isolated_path,
+ parent,
+ caller_addr);
+}
+
+libc_shared_globals* android_shared_globals() {
+ return __loader_shared_globals();
+}
+
+bool android_link_namespaces(struct android_namespace_t* namespace_from,
+ struct android_namespace_t* namespace_to,
+ const char* shared_libs_sonames) {
+ return __loader_android_link_namespaces(namespace_from, namespace_to, shared_libs_sonames);
+}
+
+void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
+ __loader_android_dlwarning(obj, f);
+}
+
+struct android_namespace_t* android_get_exported_namespace(const char* name) {
+ return __loader_android_get_exported_namespace(name);
+}
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/hybris_compat.cpp
^
|
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hybris_compat.h"
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/hybris_compat.h
^
|
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef HYBRIS_ANDROID_MM_COMPAT_H_
+#define HYBRIS_ANDROID_MM_COMPAT_H_
+
+#include <string.h>
+#include <memory.h>
+
+extern "C" size_t strlcpy(char *dest, const char *src, size_t size);
+extern "C" size_t strlcat(char *dst, const char *src, size_t size);
+
+#define ELF_ST_BIND(x) ((x) >> 4)
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+#define PAGE_MASK (~(PAGE_SIZE - 1))
+
+/*
+ * From bionic/libc/include/elf.h
+ *
+ * Experimental support for SHT_RELR sections. For details, see proposal
+ * at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+ */
+#define DT_RELR 0x6fffe000
+#define DT_RELRSZ 0x6fffe001
+#define DT_RELRENT 0x6fffe003
+#define DT_RELRCOUNT 0x6fffe005
+/*
+ * From bionic/libc/include/elf.h
+ *
+ * Android compressed rel/rela sections
+ */
+#define DT_ANDROID_REL (DT_LOOS + 2)
+#define DT_ANDROID_RELSZ (DT_LOOS + 3)
+
+#define DT_ANDROID_RELA (DT_LOOS + 4)
+#define DT_ANDROID_RELASZ (DT_LOOS + 5)
+
+/*
+ * From bionic/libc/include/bits/elf_arm64.h
+ */
+#define R_AARCH64_TLS_DTPREL64 1028 /* Module-relative offset. */
+#define R_AARCH64_TLS_DTPMOD64 1029 /* Module index. */
+#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset. */
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/ld.config.format.md
^
|
@@ -0,0 +1,86 @@
+# Linker config file format
+
+This document describes format of /system/etc/ld.config.txt file. This file can be used to customize
+linker-namespace setup for dynamic executables.
+
+## Overview
+
+The configuration consists of 2 parts
+1. Mappings - maps executable locations to sections
+2. Sections - contains linker-namespace configuration
+
+## Mappings
+
+This part of the document maps location of an executable to a section. Here is an example
+
+The format is `dir.<section_name>=<directory>`
+
+The mappings should be defined between start of ld.config.txt and the first section.
+
+## Section
+
+Every section starts with `[section_name]` (which is used in mappings) and it defines namespaces
+configuration using set of properties described in example below.
+
+## Example
+
+```
+# The following line maps section to a dir. Binraies ran from this location will use namespaces
+# configuration specified in [example_section] below
+dir.example_section=/system/bin/example
+
+# Section starts
+[example_section]
+
+# When this flag is set to true linker will set target_sdk_version for this binary to
+# the version specified in <dirname>/.version file, where <dirname> = dirname(executable_path)
+#
+# default value is false
+enable.target.sdk.version = true
+
+# This property can be used to declare additional namespaces.Note that there is always the default
+# namespace. The default namespace is the namespace for the main executable. This list is
+# comma-separated.
+additional.namespaces = ns1
+
+# Each namespace property starts with "namespace.<namespace-name>" The following is configuration
+# for the default namespace
+
+# Is namespace isolated - the default value is false
+namespace.default.isolated = true
+
+# Default namespace search path. Note that ${LIB} here is substituted with "lib" for 32bit targets
+# and with "lib64" for 64bit ones.
+namespace.default.search.paths = /system/${LIB}:/system/other/${LIB}
+
+# ... same for asan
+namespace.default.asan.search.paths = /data/${LIB}:/data/other/${LIB}
+
+# Permitted path
+namespace.default.permitted.paths = /system/${LIB}
+
+# ... asan
+namespace.default.asan.permitted.paths = /data/${LIB}
+
+# This declares linked namespaces - comma separated list.
+namespace.default.links = ns1
+
+# For every link define list of shared libraries. This is list of the libraries accessilbe from
+# default namespace but loaded in the linked namespace.
+namespace.default.link.ns1.shared_libs = libexternal.so:libother.so
+
+# This part defines config for ns1
+namespace.ns1.isolated = true
+namespace.ns1.search.paths = /vendor/${LIB}
+namespace.ns1.asan.search.paths = /data/vendor/${LIB}
+namespace.ns1.permitted.paths = /vendor/${LIB}
+namespace.ns1.asan.permitted.paths = /data/vendor/${LIB}
+
+# and links it to default namespace
+namespace.ns.links = default
+namespace.ns.link.default.shared_libs = libc.so:libdl.so:libm.so:libstdc++.so
+
+# This defines what libraries are allowed to be loaded from ns1
+namespace.ns1.whitelisted = libsomething.so
+```
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/ld_android.cpp
^
|
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+extern "C" void __internal_linker_error() {
+ __builtin_trap();
+}
+
+__strong_alias(__loader_android_create_namespace, __internal_linker_error);
+__strong_alias(__loader_android_dlopen_ext, __internal_linker_error);
+__strong_alias(__loader_android_dlwarning, __internal_linker_error);
+__strong_alias(__loader_android_get_application_target_sdk_version, __internal_linker_error);
+__strong_alias(__loader_android_get_LD_LIBRARY_PATH, __internal_linker_error);
+__strong_alias(__loader_android_get_exported_namespace, __internal_linker_error);
+__strong_alias(__loader_android_init_anonymous_namespace, __internal_linker_error);
+__strong_alias(__loader_android_link_namespaces, __internal_linker_error);
+__strong_alias(__loader_android_link_namespaces_all_libs, __internal_linker_error);
+__strong_alias(__loader_android_set_application_target_sdk_version, __internal_linker_error);
+__strong_alias(__loader_android_update_LD_LIBRARY_PATH, __internal_linker_error);
+__strong_alias(__loader_cfi_fail, __internal_linker_error);
+__strong_alias(__loader_dl_iterate_phdr, __internal_linker_error);
+__strong_alias(__loader_dladdr, __internal_linker_error);
+__strong_alias(__loader_dlclose, __internal_linker_error);
+__strong_alias(__loader_dlerror, __internal_linker_error);
+__strong_alias(__loader_dlopen, __internal_linker_error);
+__strong_alias(__loader_dlsym, __internal_linker_error);
+__strong_alias(__loader_dlvsym, __internal_linker_error);
+__strong_alias(__loader_add_thread_local_dtor, __internal_linker_error);
+__strong_alias(__loader_remove_thread_local_dtor, __internal_linker_error);
+__strong_alias(__loader_shared_globals, __internal_linker_error);
+#if defined(__arm__)
+__strong_alias(__loader_dl_unwind_find_exidx, __internal_linker_error);
+#endif
+__strong_alias(rtld_db_dlactivity, __internal_linker_error);
+
+#if defined(__arm__)
+// An arm32 unwinding table has an R_ARM_NONE relocation to
+// __aeabi_unwind_cpp_pr0. This shared library will never invoke the unwinder,
+// so it doesn't actually need the routine. Define a dummy version here,
+// because the real version calls libc functions (e.g. memcpy, abort), which
+// would create a dependency cycle with libc.so.
+__attribute__((visibility("hidden")))
+extern "C" void __aeabi_unwind_cpp_pr0() {
+ __builtin_trap();
+}
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linked_list.h
^
|
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+
+template<typename T>
+struct LinkedListEntry {
+ LinkedListEntry<T>* next;
+ T* element;
+};
+
+// ForwardInputIterator
+template<typename T>
+class LinkedListIterator {
+ public:
+ LinkedListIterator() : entry_(nullptr) {}
+ LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.entry_) {}
+ explicit LinkedListIterator(LinkedListEntry<T>* entry) : entry_(entry) {}
+
+ LinkedListIterator<T>& operator=(const LinkedListIterator<T>& that) {
+ entry_ = that.entry_;
+ return *this;
+ }
+
+ LinkedListIterator<T>& operator++() {
+ entry_ = entry_->next;
+ return *this;
+ }
+
+ T* const operator*() {
+ return entry_->element;
+ }
+
+ bool operator==(const LinkedListIterator<T>& that) const {
+ return entry_ == that.entry_;
+ }
+
+ bool operator!=(const LinkedListIterator<T>& that) const {
+ return entry_ != that.entry_;
+ }
+
+ private:
+ LinkedListEntry<T> *entry_;
+};
+
+/*
+ * Represents linked list of objects of type T
+ */
+template<typename T, typename Allocator>
+class LinkedList {
+ public:
+ typedef LinkedListIterator<T> iterator;
+ typedef T* value_type;
+
+ LinkedList() : head_(nullptr), tail_(nullptr) {}
+ ~LinkedList() {
+ clear();
+ }
+
+ LinkedList(LinkedList&& that) noexcept {
+ this->head_ = that.head_;
+ this->tail_ = that.tail_;
+ that.head_ = that.tail_ = nullptr;
+ }
+
+ void push_front(T* const element) {
+ LinkedListEntry<T>* new_entry = Allocator::alloc();
+ new_entry->next = head_;
+ new_entry->element = element;
+ head_ = new_entry;
+ if (tail_ == nullptr) {
+ tail_ = new_entry;
+ }
+ }
+
+ void push_back(T* const element) {
+ LinkedListEntry<T>* new_entry = Allocator::alloc();
+ new_entry->next = nullptr;
+ new_entry->element = element;
+ if (tail_ == nullptr) {
+ tail_ = head_ = new_entry;
+ } else {
+ tail_->next = new_entry;
+ tail_ = new_entry;
+ }
+ }
+
+ T* pop_front() {
+ if (head_ == nullptr) {
+ return nullptr;
+ }
+
+ LinkedListEntry<T>* entry = head_;
+ T* element = entry->element;
+ head_ = entry->next;
+ Allocator::free(entry);
+
+ if (head_ == nullptr) {
+ tail_ = nullptr;
+ }
+
+ return element;
+ }
+
+ T* front() const {
+ if (head_ == nullptr) {
+ return nullptr;
+ }
+
+ return head_->element;
+ }
+
+ void clear() {
+ while (head_ != nullptr) {
+ LinkedListEntry<T>* p = head_;
+ head_ = head_->next;
+ Allocator::free(p);
+ }
+
+ tail_ = nullptr;
+ }
+
+ bool empty() {
+ return (head_ == nullptr);
+ }
+
+ template<typename F>
+ void for_each(F action) const {
+ visit([&] (T* si) {
+ action(si);
+ return true;
+ });
+ }
+
+ template<typename F>
+ bool visit(F action) const {
+ for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
+ if (!action(e->element)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template<typename F>
+ void remove_if(F predicate) {
+ for (LinkedListEntry<T>* e = head_, *p = nullptr; e != nullptr;) {
+ if (predicate(e->element)) {
+ LinkedListEntry<T>* next = e->next;
+ if (p == nullptr) {
+ head_ = next;
+ } else {
+ p->next = next;
+ }
+
+ if (tail_ == e) {
+ tail_ = p;
+ }
+
+ Allocator::free(e);
+
+ e = next;
+ } else {
+ p = e;
+ e = e->next;
+ }
+ }
+ }
+
+ void remove(T* element) {
+ remove_if([&](T* e) {
+ return e == element;
+ });
+ }
+
+ template<typename F>
+ T* find_if(F predicate) const {
+ for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
+ if (predicate(e->element)) {
+ return e->element;
+ }
+ }
+
+ return nullptr;
+ }
+
+ iterator begin() const {
+ return iterator(head_);
+ }
+
+ iterator end() const {
+ return iterator(nullptr);
+ }
+
+ iterator find(T* value) const {
+ for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
+ if (e->element == value) {
+ return iterator(e);
+ }
+ }
+
+ return end();
+ }
+
+ size_t copy_to_array(T* array[], size_t array_length) const {
+ size_t sz = 0;
+ for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) {
+ array[sz++] = e->element;
+ }
+
+ return sz;
+ }
+
+ bool contains(const T* el) const {
+ for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
+ if (e->element == el) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static LinkedList make_list(T* const element) {
+ LinkedList<T, Allocator> one_element_list;
+ one_element_list.push_back(element);
+ return one_element_list;
+ }
+
+ private:
+ LinkedListEntry<T>* head_;
+ LinkedListEntry<T>* tail_;
+ DISALLOW_COPY_AND_ASSIGN(LinkedList);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linked_list_test.cpp
^
|
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string>
+#include <sstream>
+
+#include <gtest/gtest.h>
+
+#include "linked_list.h"
+
+namespace {
+
+bool alloc_called = false;
+bool free_called = false;
+
+class LinkedListTestAllocator {
+ public:
+ typedef LinkedListEntry<const char> entry_t;
+
+ static entry_t* alloc() {
+ alloc_called = true;
+ return reinterpret_cast<entry_t*>(::malloc(sizeof(entry_t)));
+ }
+
+ static void free(entry_t* p) {
+ free_called = true;
+ ::free(p);
+ }
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(LinkedListTestAllocator);
+};
+
+typedef LinkedList<const char, LinkedListTestAllocator> test_list_t;
+
+std::string test_list_to_string(test_list_t& list) {
+ std::stringstream ss;
+ list.for_each([&] (const char* c) {
+ ss << c;
+ });
+
+ return ss.str();
+}
+
+};
+
+TEST(linked_list, simple) {
+ alloc_called = free_called = false;
+ test_list_t list;
+ ASSERT_EQ("", test_list_to_string(list));
+ ASSERT_TRUE(!alloc_called);
+ ASSERT_TRUE(!free_called);
+ list.push_front("a");
+ ASSERT_TRUE(alloc_called);
+ ASSERT_TRUE(!free_called);
+ ASSERT_EQ("a", test_list_to_string(list));
+ list.push_front("b");
+ ASSERT_EQ("ba", test_list_to_string(list));
+ list.push_front("c");
+ list.push_front("d");
+ ASSERT_EQ("dcba", test_list_to_string(list));
+ ASSERT_TRUE(alloc_called);
+ ASSERT_TRUE(!free_called);
+ alloc_called = free_called = false;
+ list.remove_if([] (const char* c) {
+ return *c == 'c';
+ });
+
+ ASSERT_TRUE(!alloc_called);
+ ASSERT_TRUE(free_called);
+
+ ASSERT_EQ("dba", test_list_to_string(list));
+ alloc_called = free_called = false;
+ list.remove_if([] (const char* c) {
+ return *c == '2';
+ });
+ ASSERT_TRUE(!alloc_called);
+ ASSERT_TRUE(!free_called);
+ ASSERT_EQ("dba", test_list_to_string(list));
+ list.clear();
+ ASSERT_TRUE(!alloc_called);
+ ASSERT_TRUE(free_called);
+ ASSERT_EQ("", test_list_to_string(list));
+}
+
+TEST(linked_list, push_pop) {
+ test_list_t list;
+ list.push_front("b");
+ list.push_front("a");
+ ASSERT_EQ("ab", test_list_to_string(list));
+ list.push_back("c");
+ ASSERT_EQ("abc", test_list_to_string(list));
+ ASSERT_STREQ("a", list.pop_front());
+ ASSERT_EQ("bc", test_list_to_string(list));
+ ASSERT_STREQ("b", list.pop_front());
+ ASSERT_EQ("c", test_list_to_string(list));
+ ASSERT_STREQ("c", list.pop_front());
+ ASSERT_EQ("", test_list_to_string(list));
+ ASSERT_TRUE(list.pop_front() == nullptr);
+ list.push_back("r");
+ ASSERT_EQ("r", test_list_to_string(list));
+ ASSERT_STREQ("r", list.pop_front());
+ ASSERT_TRUE(list.pop_front() == nullptr);
+}
+
+TEST(linked_list, remove_if_then_pop) {
+ test_list_t list;
+ list.push_back("a");
+ list.push_back("b");
+ list.push_back("c");
+ list.push_back("d");
+ list.remove_if([](const char* c) {
+ return *c == 'b' || *c == 'c';
+ });
+
+ ASSERT_EQ("ad", test_list_to_string(list));
+ ASSERT_STREQ("a", list.pop_front());
+ ASSERT_EQ("d", test_list_to_string(list));
+ ASSERT_STREQ("d", list.pop_front());
+ ASSERT_TRUE(list.pop_front() == nullptr);
+}
+
+TEST(linked_list, remove_if_last_then_push_back) {
+ test_list_t list;
+
+ list.push_back("a");
+ list.push_back("b");
+ list.push_back("c");
+ list.push_back("d");
+
+ list.remove_if([](const char* c) {
+ return *c == 'c' || *c == 'd';
+ });
+
+ ASSERT_EQ("ab", test_list_to_string(list));
+ list.push_back("d");
+ ASSERT_EQ("abd", test_list_to_string(list));
+}
+
+TEST(linked_list, copy_to_array) {
+ test_list_t list;
+ const size_t max_size = 128;
+ const char* buf[max_size];
+ memset(buf, 0, sizeof(buf));
+
+ ASSERT_EQ(0U, list.copy_to_array(buf, max_size));
+ ASSERT_EQ(nullptr, buf[0]);
+
+ list.push_back("a");
+ list.push_back("b");
+ list.push_back("c");
+ list.push_back("d");
+
+ memset(buf, 0, sizeof(buf));
+ ASSERT_EQ(2U, list.copy_to_array(buf, 2));
+ ASSERT_STREQ("a", buf[0]);
+ ASSERT_STREQ("b", buf[1]);
+ ASSERT_EQ(nullptr, buf[2]);
+
+ ASSERT_EQ(4U, list.copy_to_array(buf, max_size));
+ ASSERT_STREQ("a", buf[0]);
+ ASSERT_STREQ("b", buf[1]);
+ ASSERT_STREQ("c", buf[2]);
+ ASSERT_STREQ("d", buf[3]);
+ ASSERT_EQ(nullptr, buf[4]);
+
+ memset(buf, 0, sizeof(buf));
+ list.remove_if([](const char* c) {
+ return *c != 'c';
+ });
+ ASSERT_EQ(1U, list.copy_to_array(buf, max_size));
+ ASSERT_STREQ("c", buf[0]);
+ ASSERT_EQ(nullptr, buf[1]);
+
+ memset(buf, 0, sizeof(buf));
+
+ list.remove_if([](const char* c) {
+ return *c == 'c';
+ });
+
+ ASSERT_EQ(0U, list.copy_to_array(buf, max_size));
+ ASSERT_EQ(nullptr, buf[0]);
+}
+
+TEST(linked_list, test_visit) {
+ test_list_t list;
+ list.push_back("a");
+ list.push_back("b");
+ list.push_back("c");
+ list.push_back("d");
+
+ int visits = 0;
+ std::stringstream ss;
+ bool result = list.visit([&](const char* c) {
+ ++visits;
+ ss << c;
+ return true;
+ });
+
+ ASSERT_TRUE(result);
+ ASSERT_EQ(4, visits);
+ ASSERT_EQ("abcd", ss.str());
+
+ visits = 0;
+ ss.str(std::string());
+
+ result = list.visit([&](const char* c) {
+ if (++visits == 3) {
+ return false;
+ }
+
+ ss << c;
+ return true;
+ });
+
+ ASSERT_TRUE(!result);
+ ASSERT_EQ(3, visits);
+ ASSERT_EQ("ab", ss.str());
+}
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker.arm.map
^
|
@@ -0,0 +1,29 @@
+{
+ global:
+ __loader_dlopen;
+ __loader_dlclose;
+ __loader_dlsym;
+ __loader_dlerror;
+ __loader_dladdr;
+ __loader_android_update_LD_LIBRARY_PATH;
+ __loader_android_get_LD_LIBRARY_PATH;
+ __loader_dl_iterate_phdr;
+ __loader_android_dlopen_ext;
+ __loader_android_set_application_target_sdk_version;
+ __loader_android_get_application_target_sdk_version;
+ __loader_android_init_anonymous_namespace;
+ __loader_android_create_namespace;
+ __loader_dlvsym;
+ __loader_android_dlwarning;
+ __loader_cfi_fail;
+ __loader_android_link_namespaces;
+ __loader_android_link_namespaces_all_libs;
+ __loader_android_get_exported_namespace;
+ __loader_dl_unwind_find_exidx;
+ __loader_add_thread_local_dtor;
+ __loader_remove_thread_local_dtor;
+ __loader_shared_globals;
+ rtld_db_dlactivity;
+ local:
+ *;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker.cpp
^
|
@@ -0,0 +1,4353 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <android/api-level.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+#include <new>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "hybris_compat.h"
+
+//#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
+
+#include <async_safe/log.h>
+
+// Private C library headers.
+
+#include "linker.h"
+#include "linker_block_allocator.h"
+#include "linker_cfi.h"
+#include "linker_config.h"
+#include "linker_gdb_support.h"
+#include "linker_globals.h"
+#include "linker_debug.h"
+#include "linker_dlwarning.h"
+#include "linker_main.h"
+#include "linker_namespaces.h"
+#include "linker_sleb128.h"
+#include "linker_phdr.h"
+#include "linker_relocs.h"
+#include "linker_reloc_iterators.h"
+#include "linker_tls.h"
+#include "linker_utils.h"
+
+#include "private/bionic_globals.h"
+#include "android-base/macros.h"
+//#include "android-base/strings.h"
+//#include "android-base/stringprintf.h"
+//#include "ziparchive/zip_archive.h"
+
+#ifdef WANT_ARM_TRACING
+#include "../wrappers.h"
+#endif
+
+#define TMPFS_MAGIC 0x01021994
+
+#define DF_1_PIE 0x08000000
+
+
+// Override macros to use C++ style casts.
+#undef ELF_ST_TYPE
+#define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
+
+static std::unordered_map<void*, size_t> g_dso_handle_counters;
+
+static std::unordered_map<std::string, android_namespace_t*> g_exported_namespaces;
+
+static LinkerTypeAllocator<soinfo> g_soinfo_allocator;
+static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
+
+static LinkerTypeAllocator<android_namespace_t> g_namespace_allocator;
+android_namespace_t *g_default_namespace = new (g_namespace_allocator.alloc()) android_namespace_t();
+static android_namespace_t* g_anonymous_namespace = g_default_namespace;
+static LinkerTypeAllocator<LinkedListEntry<android_namespace_t>> g_namespace_list_allocator;
+
+static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_STRING ".txt";
+
+static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
+static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
+
+#if defined(__LP64__)
+static const char* const kSystemLibDir = "/system/lib64";
+static const char* const kOdmLibDir = "/odm/lib64";
+static const char* const kVendorLibDir = "/vendor/lib64";
+static const char* const kAsanSystemLibDir = "/data/asan/system/lib64";
+static const char* const kAsanOdmLibDir = "/data/asan/odm/lib64";
+static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib64";
+static const char* const kRuntimeApexLibDir = "/apex/com.android.runtime/lib64";
+#else
+static const char* const kSystemLibDir = "/system/lib";
+static const char* const kOdmLibDir = "/odm/lib";
+static const char* const kVendorLibDir = "/vendor/lib";
+static const char* const kAsanSystemLibDir = "/data/asan/system/lib";
+static const char* const kAsanOdmLibDir = "/data/asan/odm/lib";
+static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib";
+static const char* const kRuntimeApexLibDir = "/apex/com.android.runtime/lib";
+#endif
+
+static const char* const kAsanLibDirPrefix = "/data/asan";
+
+static const char* const kDefaultLdPaths[] = {
+ kSystemLibDir,
+ kOdmLibDir,
+ kVendorLibDir,
+ nullptr
+};
+
+static const char* const kAsanDefaultLdPaths[] = {
+ kAsanSystemLibDir,
+ kSystemLibDir,
+ kAsanOdmLibDir,
+ kOdmLibDir,
+ kAsanVendorLibDir,
+ kVendorLibDir,
+ nullptr
+};
+
+// Is ASAN enabled?
+static bool g_is_asan = false;
+
+static CFIShadowWriter g_cfi_shadow;
+
+CFIShadowWriter* get_cfi_shadow() {
+ return &g_cfi_shadow;
+}
+
+static bool is_system_library(const std::string& realpath) {
+ for (const auto& dir : g_default_namespace->get_default_library_paths()) {
+ if (file_is_in_dir(realpath, dir)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Checks if the file exists and not a directory.
+static bool file_exists(const char* path) {
+ struct stat s;
+
+ if (stat(path, &s) != 0) {
+ return false;
+ }
+
+ return S_ISREG(s.st_mode);
+}
+
+static std::string resolve_soname(const std::string& name) {
+ // We assume that soname equals to basename here
+
+ // TODO(dimitry): consider having honest absolute-path -> soname resolution
+ // note that since we might end up refusing to load this library because
+ // it is not in shared libs list we need to get the soname without actually loading
+ // the library.
+ //
+ // On the other hand there are several places where we already assume that
+ // soname == basename in particular for any not-loaded library mentioned
+ // in DT_NEEDED list.
+ return basename(name.c_str());
+}
+
+static bool maybe_accessible_via_namespace_links(android_namespace_t* ns, const char* name) {
+ std::string soname = resolve_soname(name);
+ for (auto& ns_link : ns->linked_namespaces()) {
+ if (ns_link.is_accessible(soname.c_str())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
+// gradually remove libraries from this list until it is gone.
+static bool is_greylisted(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
+ static const char* const kLibraryGreyList[] = {
+ "libandroid_runtime.so",
+ "libbinder.so",
+ "libcrypto.so",
+ "libcutils.so",
+ "libexpat.so",
+ "libgui.so",
+ "libmedia.so",
+ "libnativehelper.so",
+ "libssl.so",
+ "libstagefright.so",
+ "libsqlite.so",
+ "libui.so",
+ "libutils.so",
+ "libvorbisidec.so",
+ nullptr
+ };
+
+ // If you're targeting N, you don't get the greylist.
+ if (g_greylist_disabled || get_application_target_sdk_version() >= __ANDROID_API_N__) {
+ return false;
+ }
+
+ // if the library needed by a system library - implicitly assume it
+ // is greylisted unless it is in the list of shared libraries for one or
+ // more linked namespaces
+ if (needed_by != nullptr && is_system_library(needed_by->get_realpath())) {
+ return !maybe_accessible_via_namespace_links(ns, name);
+ }
+
+ // if this is an absolute path - make sure it points to /system/lib(64)
+ if (name[0] == '/' && dirname(name) == kSystemLibDir) {
+ // and reduce the path to basename
+ name = basename(name);
+ }
+
+ for (size_t i = 0; kLibraryGreyList[i] != nullptr; ++i) {
+ if (strcmp(name, kLibraryGreyList[i]) == 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+// END OF WORKAROUND
+
+// Workaround for dlopen(/system/lib(64)/<soname>) when .so is in /apex. http://b/121248172
+/**
+ * Translate /system path to /apex path if needed
+ * The workaround should work only when targetSdkVersion < Q.
+ *
+ * param out_name_to_apex pointing to /apex path
+ * return true if translation is needed
+ */
+static bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex) {
+ static const char* const kSystemToRuntimeApexLibs[] = {
+ "libicuuc.so",
+ "libicui18n.so",
+ };
+ // New mapping for new apex should be added below
+
+ // Nothing to do if target sdk version is Q or above
+ if (get_application_target_sdk_version() >= __ANDROID_API_Q__) {
+ return false;
+ }
+
+ // If the path isn't /system/lib, there's nothing to do.
+ if (name == nullptr || dirname(name) != kSystemLibDir) {
+ return false;
+ }
+
+ const char* base_name = basename(name);
+
+ for (const char* soname : kSystemToRuntimeApexLibs) {
+ if (strcmp(base_name, soname) == 0) {
+ *out_name_to_apex = std::string(kRuntimeApexLibDir) + "/" + base_name;
+ return true;
+ }
+ }
+
+ return false;
+}
+// End Workaround for dlopen(/system/lib/<soname>) when .so is in /apex.
+
+static std::vector<std::string> g_ld_preload_names;
+
+static bool g_anonymous_namespace_initialized;
+
+#if STATS
+struct linker_stats_t {
+ int count[kRelocMax];
+};
+
+static linker_stats_t linker_stats;
+
+void count_relocation(RelocationKind kind) {
+ ++linker_stats.count[kind];
+}
+#else
+void count_relocation(RelocationKind) {
+}
+#endif
+
+#if COUNT_PAGES
+uint32_t bitmask[4096];
+#endif
+
+static void notify_gdb_of_load(soinfo* info) {
+ if (info->is_linker() || info->is_main_executable()) {
+ // gdb already knows about the linker and the main executable.
+ return;
+ }
+
+ link_map* map = &(info->link_map_head);
+
+ map->l_addr = info->load_bias;
+ // link_map l_name field is not const.
+ map->l_name = const_cast<char*>(info->get_realpath());
+ map->l_ld = info->dynamic;
+
+ CHECK(map->l_name != nullptr);
+ CHECK(map->l_name[0] != '\0');
+
+ notify_gdb_of_load(map);
+}
+
+static void notify_gdb_of_unload(soinfo* info) {
+ notify_gdb_of_unload(&(info->link_map_head));
+}
+
+LinkedListEntry<soinfo>* SoinfoListAllocator::alloc() {
+ return g_soinfo_links_allocator.alloc();
+}
+
+void SoinfoListAllocator::free(LinkedListEntry<soinfo>* entry) {
+ g_soinfo_links_allocator.free(entry);
+}
+
+LinkedListEntry<android_namespace_t>* NamespaceListAllocator::alloc() {
+ return g_namespace_list_allocator.alloc();
+}
+
+void NamespaceListAllocator::free(LinkedListEntry<android_namespace_t>* entry) {
+ g_namespace_list_allocator.free(entry);
+}
+
+soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
+ const struct stat* file_stat, off64_t file_offset,
+ uint32_t rtld_flags) {
+ if (strlen(name) >= PATH_MAX) {
+ async_safe_fatal("library name \"%s\" too long", name);
+ }
+
+ TRACE("name %s: allocating soinfo for ns=%p", name, ns);
+
+ soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(ns, name, file_stat,
+ file_offset, rtld_flags);
+
+ solist_add_soinfo(si);
+
+ si->generate_handle();
+ ns->add_soinfo(si);
+
+ TRACE("name %s: allocated soinfo @ %p", name, si);
+ return si;
+}
+
+static void soinfo_free(soinfo* si) {
+ if (si == nullptr) {
+ return;
+ }
+
+ if (si->base != 0 && si->size != 0) {
+ if (!si->is_mapped_by_caller()) {
+ munmap(reinterpret_cast<void*>(si->base), si->size);
+ } else {
+ // remap the region as PROT_NONE, MAP_ANONYMOUS | MAP_NORESERVE
+ mmap(reinterpret_cast<void*>(si->base), si->size, PROT_NONE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ }
+ }
+
+ TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
+
+ if (!solist_remove_soinfo(si)) {
+ async_safe_fatal("soinfo=%p is not in soinfo_list (double unload?)", si);
+ }
+
+ // clear links to/from si
+ si->remove_all_links();
+
+ si->~soinfo();
+ g_soinfo_allocator.free(si);
+}
+
+static void parse_path(const char* path, const char* delimiters,
+ std::vector<std::string>* resolved_paths) {
+ std::vector<std::string> paths;
+ split_path(path, delimiters, &paths);
+ resolve_paths(paths, resolved_paths);
+}
+
+static void parse_LD_LIBRARY_PATH(const char* path) {
+ std::vector<std::string> ld_libary_paths;
+ parse_path(path, ":", &ld_libary_paths);
+ g_default_namespace->set_ld_library_paths(std::move(ld_libary_paths));
+}
+
+static bool realpath_fd(int fd, std::string* realpath) {
+ std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
+ snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
+ if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
+ if (!is_first_stage_init()) {
+ PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
+ }
+ return false;
+ }
+
+ *realpath = &buf[0];
+ return true;
+}
+
+#if defined(__arm__)
+
+// For a given PC, find the .so that it belongs to.
+// Returns the base address of the .ARM.exidx section
+// for that .so, and the number of 8-byte entries
+// in that section (via *pcount).
+//
+// Intended to be called by libc's __gnu_Unwind_Find_exidx().
+_Unwind_Ptr do_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
+ if (soinfo* si = find_containing_library(reinterpret_cast<void*>(pc))) {
+ *pcount = si->ARM_exidx_count;
+ return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx);
+ }
+ *pcount = 0;
+ return 0;
+}
+
+#endif
+
+// Here, we only have to provide a callback to iterate across all the
+// loaded libraries. gcc_eh does the rest.
+int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
+ int rv = 0;
+ for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
+ dl_phdr_info dl_info;
+ dl_info.dlpi_addr = si->link_map_head.l_addr;
+ dl_info.dlpi_name = si->link_map_head.l_name;
+ dl_info.dlpi_phdr = si->phdr;
+ dl_info.dlpi_phnum = si->phnum;
+ rv = cb(&dl_info, sizeof(dl_phdr_info), data);
+ if (rv != 0) {
+ break;
+ }
+ }
+ return rv;
+}
+
+
+bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
+ soinfo** si_found_in, const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group, const ElfW(Sym)** symbol) {
+ SymbolName symbol_name(name);
+ const ElfW(Sym)* s = nullptr;
+
+ /* "This element's presence in a shared object library alters the dynamic linker's
+ * symbol resolution algorithm for references within the library. Instead of starting
+ * a symbol search with the executable file, the dynamic linker starts from the shared
+ * object itself. If the shared object fails to supply the referenced symbol, the
+ * dynamic linker then searches the executable file and other shared objects as usual."
+ *
+ * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html
+ *
+ * Note that this is unlikely since static linker avoids generating
+ * relocations for -Bsymbolic linked dynamic executables.
+ */
+ if (si_from->has_DT_SYMBOLIC) {
+ DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_realpath(), name);
+ if (!si_from->find_symbol_by_name(symbol_name, vi, &s)) {
+ return false;
+ }
+
+ if (s != nullptr) {
+ *si_found_in = si_from;
+ }
+ }
+
+ // 1. Look for it in global_group
+ if (s == nullptr) {
+ bool error = false;
+ global_group.visit([&](soinfo* global_si) {
+ DEBUG("%s: looking up %s in %s (from global group)",
+ si_from->get_realpath(), name, global_si->get_realpath());
+ if (!global_si->find_symbol_by_name(symbol_name, vi, &s)) {
+ error = true;
+ return false;
+ }
+
+ if (s != nullptr) {
+ *si_found_in = global_si;
+ return false;
+ }
+
+ return true;
+ });
+
+ if (error) {
+ return false;
+ }
+ }
+
+ // 2. Look for it in the local group
+ if (s == nullptr) {
+ bool error = false;
+ local_group.visit([&](soinfo* local_si) {
+ if (local_si == si_from && si_from->has_DT_SYMBOLIC) {
+ // we already did this - skip
+ return true;
+ }
+
+ DEBUG("%s: looking up %s in %s (from local group)",
+ si_from->get_realpath(), name, local_si->get_realpath());
+ if (!local_si->find_symbol_by_name(symbol_name, vi, &s)) {
+ error = true;
+ return false;
+ }
+
+ if (s != nullptr) {
+ *si_found_in = local_si;
+ return false;
+ }
+
+ return true;
+ });
+
+ if (error) {
+ return false;
+ }
+ }
+
+ if (s != nullptr) {
+ TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
+ "found in %s, base = %p, load bias = %p",
+ si_from->get_realpath(), name, reinterpret_cast<void*>(s->st_value),
+ (*si_found_in)->get_realpath(), reinterpret_cast<void*>((*si_found_in)->base),
+ reinterpret_cast<void*>((*si_found_in)->load_bias));
+ }
+
+ *symbol = s;
+ return true;
+}
+
+ProtectedDataGuard::ProtectedDataGuard() {
+ if (ref_count_++ == 0) {
+ protect_data(PROT_READ | PROT_WRITE);
+ }
+
+ if (ref_count_ == 0) { // overflow
+ async_safe_fatal("Too many nested calls to dlopen()");
+ }
+}
+
+ProtectedDataGuard::~ProtectedDataGuard() {
+ if (--ref_count_ == 0) {
+ protect_data(PROT_READ);
+ }
+}
+
+void ProtectedDataGuard::protect_data(int protection) {
+ g_soinfo_allocator.protect_all(protection);
+ g_soinfo_links_allocator.protect_all(protection);
+ g_namespace_allocator.protect_all(protection);
+ g_namespace_list_allocator.protect_all(protection);
+}
+
+size_t ProtectedDataGuard::ref_count_ = 0;
+
+// Each size has it's own allocator.
+template<size_t size>
+class SizeBasedAllocator {
+ public:
+ static void* alloc() {
+ return allocator_.alloc();
+ }
+
+ static void free(void* ptr) {
+ allocator_.free(ptr);
+ }
+
+ static void purge() {
+ allocator_.purge();
+ }
+
+ private:
+ static LinkerBlockAllocator allocator_;
+};
+
+template<size_t size>
+LinkerBlockAllocator SizeBasedAllocator<size>::allocator_(size);
+
+template<typename T>
+class TypeBasedAllocator {
+ public:
+ static T* alloc() {
+ return reinterpret_cast<T*>(SizeBasedAllocator<sizeof(T)>::alloc());
+ }
+
+ static void free(T* ptr) {
+ SizeBasedAllocator<sizeof(T)>::free(ptr);
+ }
+
+ static void purge() {
+ SizeBasedAllocator<sizeof(T)>::purge();
+ }
+};
+
+class LoadTask {
+ public:
+ struct deleter_t {
+ void operator()(LoadTask* t) {
+ t->~LoadTask();
+ TypeBasedAllocator<LoadTask>::free(t);
+ }
+ };
+
+ static deleter_t deleter;
+
+ static LoadTask* create(const char* name,
+ soinfo* needed_by,
+ android_namespace_t* start_from,
+ std::unordered_map<const soinfo*, ElfReader>* readers_map) {
+ LoadTask* ptr = TypeBasedAllocator<LoadTask>::alloc();
+ return new (ptr) LoadTask(name, needed_by, start_from, readers_map);
+ }
+
+ const char* get_name() const {
+ return name_;
+ }
+
+ soinfo* get_needed_by() const {
+ return needed_by_;
+ }
+
+ soinfo* get_soinfo() const {
+ return si_;
+ }
+
+ void set_soinfo(soinfo* si) {
+ si_ = si;
+ }
+
+ off64_t get_file_offset() const {
+ return file_offset_;
+ }
+
+ void set_file_offset(off64_t offset) {
+ file_offset_ = offset;
+ }
+
+ int get_fd() const {
+ return fd_;
+ }
+
+ void set_fd(int fd, bool assume_ownership) {
+ if (fd_ != -1 && close_fd_) {
+ close(fd_);
+ }
+ fd_ = fd;
+ close_fd_ = assume_ownership;
+ }
+
+ const android_dlextinfo* get_extinfo() const {
+ return extinfo_;
+ }
+
+ void set_extinfo(const android_dlextinfo* extinfo) {
+ extinfo_ = extinfo;
+ }
+
+ bool is_dt_needed() const {
+ return is_dt_needed_;
+ }
+
+ void set_dt_needed(bool is_dt_needed) {
+ is_dt_needed_ = is_dt_needed;
+ }
+
+ // returns the namespace from where we need to start loading this.
+ const android_namespace_t* get_start_from() const {
+ return start_from_;
+ }
+
+ const ElfReader& get_elf_reader() const {
+ CHECK(si_ != nullptr);
+ return (*elf_readers_map_)[si_];
+ }
+
+ ElfReader& get_elf_reader() {
+ CHECK(si_ != nullptr);
+ return (*elf_readers_map_)[si_];
+ }
+
+ std::unordered_map<const soinfo*, ElfReader>* get_readers_map() {
+ return elf_readers_map_;
+ }
+
+ bool read(const char* realpath, off64_t file_size) {
+ ElfReader& elf_reader = get_elf_reader();
+ return elf_reader.Read(realpath, fd_, file_offset_, file_size);
+ }
+
+ bool load(address_space_params* address_space) {
+ ElfReader& elf_reader = get_elf_reader();
+ if (!elf_reader.Load(address_space)) {
+ return false;
+ }
+
+ si_->base = elf_reader.load_start();
+ si_->size = elf_reader.load_size();
+ si_->set_mapped_by_caller(elf_reader.is_mapped_by_caller());
+ si_->load_bias = elf_reader.load_bias();
+ si_->phnum = elf_reader.phdr_count();
+ si_->phdr = elf_reader.loaded_phdr();
+
+ return true;
+ }
+
+ private:
+ LoadTask(const char* name,
+ soinfo* needed_by,
+ android_namespace_t* start_from,
+ std::unordered_map<const soinfo*, ElfReader>* readers_map)
+ : name_(name), needed_by_(needed_by), si_(nullptr),
+ fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map),
+ is_dt_needed_(false), start_from_(start_from) {}
+
+ ~LoadTask() {
+ if (fd_ != -1 && close_fd_) {
+ close(fd_);
+ }
+ }
+
+ const char* name_;
+ soinfo* needed_by_;
+ soinfo* si_;
+ const android_dlextinfo* extinfo_;
+ int fd_;
+ bool close_fd_;
+ off64_t file_offset_;
+ std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_;
+ // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list)
+ bool is_dt_needed_;
+ // END OF WORKAROUND
+ const android_namespace_t* const start_from_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask);
+};
+
+LoadTask::deleter_t LoadTask::deleter;
+
+template <typename T>
+using linked_list_t = LinkedList<T, TypeBasedAllocator<LinkedListEntry<T>>>;
+
+typedef linked_list_t<soinfo> SoinfoLinkedList;
+typedef linked_list_t<const char> StringLinkedList;
+typedef std::vector<LoadTask*> LoadTaskList;
+
+enum walk_action_result_t : uint32_t {
+ kWalkStop = 0,
+ kWalkContinue = 1,
+ kWalkSkip = 2
+};
+
+// This function walks down the tree of soinfo dependencies
+// in breadth-first order and
+// * calls action(soinfo* si) for each node, and
+// * terminates walk if action returns kWalkStop
+// * skips children of the node if action
+// return kWalkSkip
+//
+// walk_dependencies_tree returns false if walk was terminated
+// by the action and true otherwise.
+template<typename F>
+static bool walk_dependencies_tree(soinfo* root_soinfo, F action) {
+ SoinfoLinkedList visit_list;
+ SoinfoLinkedList visited;
+
+ visit_list.push_back(root_soinfo);
+
+ soinfo* si;
+ while ((si = visit_list.pop_front()) != nullptr) {
+ if (visited.contains(si)) {
+ continue;
+ }
+
+ walk_action_result_t result = action(si);
+
+ if (result == kWalkStop) {
+ return false;
+ }
+
+ visited.push_back(si);
+
+ if (result != kWalkSkip) {
+ si->get_children().for_each([&](soinfo* child) {
+ visit_list.push_back(child);
+ });
+ }
+ }
+
+ return true;
+}
+
+
+static const ElfW(Sym)* dlsym_handle_lookup(android_namespace_t* ns,
+ soinfo* root,
+ soinfo* skip_until,
+ soinfo** found,
+ SymbolName& symbol_name,
+ const version_info* vi) {
+ const ElfW(Sym)* result = nullptr;
+ bool skip_lookup = skip_until != nullptr;
+
+ walk_dependencies_tree(root, [&](soinfo* current_soinfo) {
+ if (skip_lookup) {
+ skip_lookup = current_soinfo != skip_until;
+ return kWalkContinue;
+ }
+
+ if (!ns->is_accessible(current_soinfo)) {
+ return kWalkSkip;
+ }
+
+ if (!current_soinfo->find_symbol_by_name(symbol_name, vi, &result)) {
+ result = nullptr;
+ return kWalkStop;
+ }
+
+ if (result != nullptr) {
+ *found = current_soinfo;
+ return kWalkStop;
+ }
+
+ return kWalkContinue;
+ });
+
+ return result;
+}
+
+static const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
+ const char* name,
+ const version_info* vi,
+ soinfo** found,
+ soinfo* caller,
+ void* handle);
+
+// This is used by dlsym(3). It performs symbol lookup only within the
+// specified soinfo object and its dependencies in breadth first order.
+static const ElfW(Sym)* dlsym_handle_lookup(soinfo* si,
+ soinfo** found,
+ const char* name,
+ const version_info* vi) {
+ // According to man dlopen(3) and posix docs in the case when si is handle
+ // of the main executable we need to search not only in the executable and its
+ // dependencies but also in all libraries loaded with RTLD_GLOBAL.
+ //
+ // Since RTLD_GLOBAL is always set for the main executable and all dt_needed shared
+ // libraries and they are loaded in breath-first (correct) order we can just execute
+ // dlsym(RTLD_DEFAULT, ...); instead of doing two stage lookup.
+ if (si == solist_get_somain()) {
+ return dlsym_linear_lookup(g_default_namespace, name, vi, found, nullptr, RTLD_DEFAULT);
+ }
+
+ SymbolName symbol_name(name);
+ // note that the namespace is not the namespace associated with caller_addr
+ // we use ns associated with root si intentionally here. Using caller_ns
+ // causes problems when user uses dlopen_ext to open a library in the separate
+ // namespace and then calls dlsym() on the handle.
+ return dlsym_handle_lookup(si->get_primary_namespace(), si, nullptr, found, symbol_name, vi);
+}
+
+/* This is used by dlsym(3) to performs a global symbol lookup. If the
+ start value is null (for RTLD_DEFAULT), the search starts at the
+ beginning of the global solist. Otherwise the search starts at the
+ specified soinfo (for RTLD_NEXT).
+ */
+static const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
+ const char* name,
+ const version_info* vi,
+ soinfo** found,
+ soinfo* caller,
+ void* handle) {
+ SymbolName symbol_name(name);
+
+ auto& soinfo_list = ns->soinfo_list();
+ auto start = soinfo_list.begin();
+
+ if (handle == RTLD_NEXT) {
+ if (caller == nullptr) {
+ return nullptr;
+ } else {
+ auto it = soinfo_list.find(caller);
+ CHECK (it != soinfo_list.end());
+ start = ++it;
+ }
+ }
+
+ const ElfW(Sym)* s = nullptr;
+ for (auto it = start, end = soinfo_list.end(); it != end; ++it) {
+ soinfo* si = *it;
+ // Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...)
+ // if the library is opened by application with target api level < M.
+ // See http://b/21565766
+ if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0 &&
+ si->get_target_sdk_version() >= __ANDROID_API_M__) {
+ continue;
+ }
+
+ if (!si->find_symbol_by_name(symbol_name, vi, &s)) {
+ return nullptr;
+ }
+
+ if (s != nullptr) {
+ *found = si;
+ break;
+ }
+ }
+
+ // If not found - use dlsym_handle_lookup for caller's local_group
+ if (s == nullptr && caller != nullptr) {
+ soinfo* local_group_root = caller->get_local_group_root();
+
+ return dlsym_handle_lookup(local_group_root->get_primary_namespace(),
+ local_group_root,
+ (handle == RTLD_NEXT) ? caller : nullptr,
+ found,
+ symbol_name,
+ vi);
+ }
+
+ if (s != nullptr) {
+ TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
+ name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
+ }
+
+ return s;
+}
+
+soinfo* find_containing_library(const void* p) {
+ ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(p);
+ for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
+ if (address < si->base || address - si->base >= si->size) {
+ continue;
+ }
+ ElfW(Addr) vaddr = address - si->load_bias;
+ for (size_t i = 0; i != si->phnum; ++i) {
+ const ElfW(Phdr)* phdr = &si->phdr[i];
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+ if (vaddr >= phdr->p_vaddr && vaddr < phdr->p_vaddr + phdr->p_memsz) {
+ return si;
+ }
+ }
+ }
+ return nullptr;
+}
+
+class ZipArchiveCache {
+ public:
+ ZipArchiveCache() {}
+ ~ZipArchiveCache() {};
+
+ //bool get_or_open(const char* zip_path, ZipArchiveHandle* handle);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ZipArchiveCache);
+
+ //std::unordered_map<std::string, ZipArchiveHandle> cache_;
+};
+/*
+bool ZipArchiveCache::get_or_open(const char* zip_path, ZipArchiveHandle* handle) {
+ std::string key(zip_path);
+
+ auto it = cache_.find(key);
+ if (it != cache_.end()) {
+ *handle = it->second;
+ return true;
+ }
+
+ int fd = TEMP_FAILURE_RETRY(open(zip_path, O_RDONLY | O_CLOEXEC));
+ if (fd == -1) {
+ return false;
+ }
+
+ if (OpenArchiveFd(fd, "", handle) != 0) {
+ // invalid zip-file (?)
+ CloseArchive(*handle);
+ return false;
+ }
+
+ cache_[key] = *handle;
+ return true;
+}
+
+ZipArchiveCache::~ZipArchiveCache() {
+ for (const auto& it : cache_) {
+ CloseArchive(it.second);
+ }
+}
+
+static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
+ const char* const input_path,
+ off64_t* file_offset, std::string* realpath) {
+ std::string normalized_path;
+ if (!normalize_path(input_path, &normalized_path)) {
+ return -1;
+ }
+
+ const char* const path = normalized_path.c_str();
+ TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+
+ // Treat an '!/' separator inside a path as the separator between the name
+ // of the zip file on disk and the subdirectory to search within it.
+ // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
+ // "bar/bas/x.so" within "foo.zip".
+ const char* const separator = strstr(path, kZipFileSeparator);
+ if (separator == nullptr) {
+ return -1;
+ }
+
+ char buf[512];
+ if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
+ PRINT("Warning: ignoring very long library path: %s", path);
+ return -1;
+ }
+
+ buf[separator - path] = '\0';
+
+ const char* zip_path = buf;
+ const char* file_path = &buf[separator - path + 2];
+ int fd = TEMP_FAILURE_RETRY(open(zip_path, O_RDONLY | O_CLOEXEC));
+ if (fd == -1) {
+ return -1;
+ }
+
+ ZipArchiveHandle handle;
+ if (!zip_archive_cache->get_or_open(zip_path, &handle)) {
+ // invalid zip-file (?)
+ close(fd);
+ return -1;
+ }
+
+ ZipEntry entry;
+
+ if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
+ // Entry was not found.
+ close(fd);
+ return -1;
+ }
+
+ // Check if it is properly stored
+ if (entry.method != kCompressStored || (entry.offset % PAGE_SIZE) != 0) {
+ close(fd);
+ return -1;
+ }
+
+ *file_offset = entry.offset;
+
+ if (realpath_fd(fd, realpath)) {
+ *realpath += separator;
+ } else {
+ if (!is_first_stage_init()) {
+ PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
+ normalized_path.c_str());
+ }
+ *realpath = normalized_path;
+ }
+
+ return fd;
+}
+*/
+static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
+ int n = snprintf(buf, buf_size, "%s/%s", path, name);
+ if (n < 0 || n >= static_cast<int>(buf_size)) {
+ PRINT("Warning: ignoring very long library path: %s/%s", path, name);
+ return false;
+ }
+
+ return true;
+}
+
+static int open_library_at_path(ZipArchiveCache* zip_archive_cache,
+ const char* path, off64_t* file_offset,
+ std::string* realpath) {
+ int fd = -1;
+ /*
+ if (strstr(path, kZipFileSeparator) != nullptr) {
+ fd = open_library_in_zipfile(zip_archive_cache, path, file_offset, realpath);
+ }
+ */
+ if (fd == -1) {
+ fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
+ if (fd != -1) {
+ *file_offset = 0;
+ if (!realpath_fd(fd, realpath)) {
+ if (!is_first_stage_init()) {
+ PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
+ path);
+ }
+ *realpath = path;
+ }
+ }
+ }
+
+ return fd;
+}
+
+static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
+ const char* name, off64_t* file_offset,
+ const std::vector<std::string>& paths,
+ std::string* realpath) {
+ for (const auto& path : paths) {
+ char buf[512];
+ if (!format_path(buf, sizeof(buf), path.c_str(), name)) {
+ continue;
+ }
+
+ int fd = open_library_at_path(zip_archive_cache, buf, file_offset, realpath);
+ if (fd != -1) {
+ return fd;
+ }
+ }
+
+ return -1;
+}
+
+static int open_library(android_namespace_t* ns,
+ ZipArchiveCache* zip_archive_cache,
+ const char* name, soinfo *needed_by,
+ off64_t* file_offset, std::string* realpath) {
+ TRACE("[ opening %s from namespace %s ]", name, ns->get_name());
+
+ // If the name contains a slash, we should attempt to open it directly and not search the paths.
+ if (strchr(name, '/') != nullptr) {
+ int fd = -1;
+
+ /*if (strstr(name, kZipFileSeparator) != nullptr) {
+ fd = open_library_in_zipfile(zip_archive_cache, name, file_offset, realpath);
+ }
+ */
+ if (fd == -1) {
+ fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC));
+ if (fd != -1) {
+ *file_offset = 0;
+ if (!realpath_fd(fd, realpath)) {
+ if (!is_first_stage_init()) {
+ PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
+ name);
+ }
+ *realpath = name;
+ }
+ }
+ }
+
+ return fd;
+ }
+
+ // Otherwise we try LD_LIBRARY_PATH first, and fall back to the default library path
+ TRACE("[ opening %s from namespace %s from %s]", name, ns->get_name(),ns->get_ld_library_paths());
+ int fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_ld_library_paths(), realpath);
+ if (fd == -1 && needed_by != nullptr) {
+ TRACE("[ opening %s from namespace %s from %s]", name, ns->get_name(),needed_by->get_dt_runpath());
+ fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath(), realpath);
+ // Check if the library is accessible
+ if (fd != -1 && !ns->is_accessible(*realpath)) {
+ close(fd);
+ fd = -1;
+ }
+ }
+
+ if (fd == -1) {
+ TRACE("[ opening %s from namespace %s from %s]", name, ns->get_name(),ns->get_default_library_paths());
+ fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_default_library_paths(), realpath);
+ }
+
+ return fd;
+}
+
+int open_executable(const char* path, off64_t* file_offset, std::string* realpath) {
+ ZipArchiveCache zip_archive_cache;
+ return open_library_at_path(&zip_archive_cache, path, file_offset, realpath);
+}
+
+const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) {
+#if !defined(__LP64__)
+ // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029
+ int app_target_api_level = get_application_target_sdk_version();
+ if (app_target_api_level < __ANDROID_API_M__) {
+ const char* bname = basename(dt_needed);
+ if (bname != dt_needed) {
+ DL_WARN_documented_change(__ANDROID_API_M__,
+ "invalid-dt_needed-entries-enforced-for-api-level-23",
+ "library \"%s\" has invalid DT_NEEDED entry \"%s\"",
+ sopath, dt_needed, app_target_api_level);
+ add_dlwarning(sopath, "invalid DT_NEEDED entry", dt_needed);
+ }
+
+ return bname;
+ }
+#endif
+ return dt_needed;
+}
+
+template<typename F>
+static void for_each_dt_needed(const ElfReader& elf_reader, F action) {
+ for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_NEEDED) {
+ action(fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name()));
+ }
+ }
+}
+
+static bool find_loaded_library_by_inode(android_namespace_t* ns,
+ const struct stat& file_stat,
+ off64_t file_offset,
+ bool search_linked_namespaces,
+ soinfo** candidate) {
+
+ auto predicate = [&](soinfo* si) {
+ return si->get_st_dev() != 0 &&
+ si->get_st_ino() != 0 &&
+ si->get_st_dev() == file_stat.st_dev &&
+ si->get_st_ino() == file_stat.st_ino &&
+ si->get_file_offset() == file_offset;
+ };
+
+ *candidate = ns->soinfo_list().find_if(predicate);
+
+ if (*candidate == nullptr && search_linked_namespaces) {
+ for (auto& link : ns->linked_namespaces()) {
+ android_namespace_t* linked_ns = link.linked_namespace();
+ soinfo* si = linked_ns->soinfo_list().find_if(predicate);
+
+ if (si != nullptr && link.is_accessible(si->get_soname())) {
+ *candidate = si;
+ return true;
+ }
+ }
+ }
+
+ return *candidate != nullptr;
+}
+
+static bool find_loaded_library_by_realpath(android_namespace_t* ns, const char* realpath,
+ bool search_linked_namespaces, soinfo** candidate) {
+ auto predicate = [&](soinfo* si) { return strcmp(realpath, si->get_realpath()) == 0; };
+
+ *candidate = ns->soinfo_list().find_if(predicate);
+
+ if (*candidate == nullptr && search_linked_namespaces) {
+ for (auto& link : ns->linked_namespaces()) {
+ android_namespace_t* linked_ns = link.linked_namespace();
+ soinfo* si = linked_ns->soinfo_list().find_if(predicate);
+
+ if (si != nullptr && link.is_accessible(si->get_soname())) {
+ *candidate = si;
+ return true;
+ }
+ }
+ }
+
+ return *candidate != nullptr;
+}
+
+static bool load_library(android_namespace_t* ns,
+ LoadTask* task,
+ LoadTaskList* load_tasks,
+ int rtld_flags,
+ const std::string& realpath,
+ bool search_linked_namespaces) {
+ off64_t file_offset = task->get_file_offset();
+ const char* name = task->get_name();
+ const android_dlextinfo* extinfo = task->get_extinfo();
+
+ LD_LOG(kLogDlopen, "load_library(ns=%s, task=%s, flags=0x%x, realpath=%s)", ns->get_name(), name,
+ rtld_flags, realpath.c_str());
+
+ if ((file_offset % PAGE_SIZE) != 0) {
+ DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
+ return false;
+ }
+ if (file_offset < 0) {
+ DL_ERR("file offset for the library \"%s\" is negative: %" PRId64, name, file_offset);
+ return false;
+ }
+
+ struct stat file_stat;
+ if (TEMP_FAILURE_RETRY(fstat(task->get_fd(), &file_stat)) != 0) {
+ DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno));
+ return false;
+ }
+ if (file_offset >= file_stat.st_size) {
+ DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64,
+ name, file_offset, file_stat.st_size);
+ return false;
+ }
+
+ // Check for symlink and other situations where
+ // file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
+ if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
+ soinfo* si = nullptr;
+ if (find_loaded_library_by_inode(ns, file_stat, file_offset, search_linked_namespaces, &si)) {
+ LD_LOG(kLogDlopen,
+ "load_library(ns=%s, task=%s): Already loaded under different name/path \"%s\" - "
+ "will return existing soinfo",
+ ns->get_name(), name, si->get_realpath());
+ task->set_soinfo(si);
+ return true;
+ }
+ }
+
+ if ((rtld_flags & RTLD_NOLOAD) != 0) {
+ DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name);
+ return false;
+ }
+
+ struct statfs fs_stat;
+ if (TEMP_FAILURE_RETRY(fstatfs(task->get_fd(), &fs_stat)) != 0) {
+ DL_ERR("unable to fstatfs file for the library \"%s\": %s", name, strerror(errno));
+ return false;
+ }
+
+ // do not check accessibility using realpath if fd is located on tmpfs
+ // this enables use of memfd_create() for apps
+ if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
+ // TODO(dimitry): workaround for http://b/26394120 - the grey-list
+
+ // TODO(dimitry) before O release: add a namespace attribute to have this enabled
+ // only for classloader-namespaces
+ const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
+ if (is_greylisted(ns, name, needed_by)) {
+ // print warning only if needed by non-system library
+ if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
+ const soinfo* needed_or_dlopened_by = task->get_needed_by();
+ const char* sopath = needed_or_dlopened_by == nullptr ? "(unknown)" :
+ needed_or_dlopened_by->get_realpath();
+ DL_WARN_documented_change(__ANDROID_API_N__,
+ "private-api-enforced-for-api-level-24",
+ "library \"%s\" (\"%s\") needed or dlopened by \"%s\" "
+ "is not accessible by namespace \"%s\"",
+ name, realpath.c_str(), sopath, ns->get_name());
+ add_dlwarning(sopath, "unauthorized access to", name);
+ }
+ } else {
+ // do not load libraries if they are not accessible for the specified namespace.
+ const char* needed_or_dlopened_by = task->get_needed_by() == nullptr ?
+ "(unknown)" :
+ task->get_needed_by()->get_realpath();
+
+ DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"",
+ name, needed_or_dlopened_by, ns->get_name());
+
+ // do not print this if a library is in the list of shared libraries for linked namespaces
+ if (!maybe_accessible_via_namespace_links(ns, name)) {
+ PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
+ " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
+ " permitted_paths=\"%s\"]",
+ name, realpath.c_str(),
+ needed_or_dlopened_by,
+ ns->get_name(),
+ join(ns->get_ld_library_paths(), ':').c_str(),
+ join(ns->get_default_library_paths(), ':').c_str(),
+ join(ns->get_permitted_paths(), ':').c_str());
+ }
+ return false;
+ }
+ }
+
+ soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags);
+ if (si == nullptr) {
+ return false;
+ }
+
+ task->set_soinfo(si);
+
+ // Read the ELF header and some of the segments.
+ if (!task->read(realpath.c_str(), file_stat.st_size)) {
+ soinfo_free(si);
+ task->set_soinfo(nullptr);
+ return false;
+ }
+
+ // find and set DT_RUNPATH and dt_soname
+ // Note that these field values are temporary and are
+ // going to be overwritten on soinfo::prelink_image
+ // with values from PT_LOAD segments.
+ const ElfReader& elf_reader = task->get_elf_reader();
+ for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_RUNPATH) {
+ si->set_dt_runpath(elf_reader.get_string(d->d_un.d_val));
+ }
+ if (d->d_tag == DT_SONAME) {
+ si->set_soname(elf_reader.get_string(d->d_un.d_val));
+ }
+ }
+
+#if !defined(__ANDROID__)
+ // Bionic on the host currently uses some Android prebuilts, which don't set
+ // DT_RUNPATH with any relative paths, so they can't find their dependencies.
+ // b/118058804
+ if (si->get_dt_runpath().empty()) {
+ si->set_dt_runpath("$ORIGIN/../lib64:$ORIGIN/lib64");
+ }
+#endif
+
+ for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
+ LD_LOG(kLogDlopen, "load_library(ns=%s, task=%s): Adding DT_NEEDED task: %s",
+ ns->get_name(), task->get_name(), name);
+ load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
+ });
+
+ return true;
+}
+
+static bool load_library(android_namespace_t* ns,
+ LoadTask* task,
+ ZipArchiveCache* zip_archive_cache,
+ LoadTaskList* load_tasks,
+ int rtld_flags,
+ bool search_linked_namespaces) {
+ const char* name = task->get_name();
+ soinfo* needed_by = task->get_needed_by();
+ const android_dlextinfo* extinfo = task->get_extinfo();
+
+ off64_t file_offset;
+ std::string realpath;
+ if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
+ file_offset = 0;
+ if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
+ file_offset = extinfo->library_fd_offset;
+ }
+
+ if (!realpath_fd(extinfo->library_fd, &realpath)) {
+ if (!is_first_stage_init()) {
+ PRINT(
+ "warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
+ "Will use given name.",
+ name);
+ }
+ realpath = name;
+ }
+
+ task->set_fd(extinfo->library_fd, false);
+ task->set_file_offset(file_offset);
+ return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
+ }
+
+ // Open the file.
+ int fd = open_library(ns, zip_archive_cache, name, needed_by, &file_offset, &realpath);
+ if (fd == -1) {
+ DL_ERR("library \"%s\" not found", name);
+ return false;
+ }
+
+ task->set_fd(fd, true);
+ task->set_file_offset(file_offset);
+
+ return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
+}
+
+static bool find_loaded_library_by_soname(android_namespace_t* ns,
+ const char* name,
+ soinfo** candidate) {
+ return !ns->soinfo_list().visit([&](soinfo* si) {
+ const char* soname = si->get_soname();
+ if (soname != nullptr && (strcmp(name, soname) == 0)) {
+ *candidate = si;
+ return false;
+ }
+
+ return true;
+ });
+}
+
+// Returns true if library was found and false otherwise
+static bool find_loaded_library_by_soname(android_namespace_t* ns,
+ const char* name,
+ bool search_linked_namespaces,
+ soinfo** candidate) {
+ *candidate = nullptr;
+
+ // Ignore filename with path.
+ if (strchr(name, '/') != nullptr) {
+ return false;
+ }
+
+ bool found = find_loaded_library_by_soname(ns, name, candidate);
+
+ if (!found && search_linked_namespaces) {
+ // if a library was not found - look into linked namespaces
+ for (auto& link : ns->linked_namespaces()) {
+ if (!link.is_accessible(name)) {
+ continue;
+ }
+
+ android_namespace_t* linked_ns = link.linked_namespace();
+
+ if (find_loaded_library_by_soname(linked_ns, name, candidate)) {
+ return true;
+ }
+ }
+ }
+
+ return found;
+}
+
+static bool find_library_in_linked_namespace(const android_namespace_link_t& namespace_link,
+ LoadTask* task) {
+ android_namespace_t* ns = namespace_link.linked_namespace();
+
+ soinfo* candidate;
+ bool loaded = false;
+
+ std::string soname;
+ if (find_loaded_library_by_soname(ns, task->get_name(), false, &candidate)) {
+ loaded = true;
+ soname = candidate->get_soname();
+ } else {
+ soname = resolve_soname(task->get_name());
+ }
+
+ if (!namespace_link.is_accessible(soname.c_str())) {
+ // the library is not accessible via namespace_link
+ LD_LOG(kLogDlopen,
+ "find_library_in_linked_namespace(ns=%s, task=%s): Not accessible (soname=%s)",
+ ns->get_name(), task->get_name(), soname.c_str());
+ return false;
+ }
+
+ // if library is already loaded - return it
+ if (loaded) {
+ LD_LOG(kLogDlopen, "find_library_in_linked_namespace(ns=%s, task=%s): Already loaded",
+ ns->get_name(), task->get_name());
+ task->set_soinfo(candidate);
+ return true;
+ }
+
+ // returning true with empty soinfo means that the library is okay to be
+ // loaded in the namespace but has not yet been loaded there before.
+ LD_LOG(kLogDlopen, "find_library_in_linked_namespace(ns=%s, task=%s): Ok to load", ns->get_name(),
+ task->get_name());
+ task->set_soinfo(nullptr);
+ return true;
+}
+
+static bool find_library_internal(android_namespace_t* ns,
+ LoadTask* task,
+ ZipArchiveCache* zip_archive_cache,
+ LoadTaskList* load_tasks,
+ int rtld_flags,
+ bool search_linked_namespaces) {
+ soinfo* candidate;
+
+ if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {
+ LD_LOG(kLogDlopen,
+ "find_library_internal(ns=%s, task=%s): Already loaded (by soname): %s",
+ ns->get_name(), task->get_name(), candidate->get_realpath());
+ task->set_soinfo(candidate);
+ return true;
+ }
+
+ // Library might still be loaded, the accurate detection
+ // of this fact is done by load_library.
+ TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
+ task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
+
+ if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {
+ return true;
+ }
+
+ // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
+ if (ns->is_greylist_enabled() && is_greylisted(ns, task->get_name(), task->get_needed_by())) {
+ // For the libs in the greylist, switch to the default namespace and then
+ // try the load again from there. The library could be loaded from the
+ // default namespace or from another namespace (e.g. runtime) that is linked
+ // from the default namespace.
+ LD_LOG(kLogDlopen,
+ "find_library_internal(ns=%s, task=%s): Greylisted library - trying namespace %s",
+ ns->get_name(), task->get_name(), g_default_namespace->get_name());
+ ns = g_default_namespace;
+ if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
+ search_linked_namespaces)) {
+ return true;
+ }
+ }
+ // END OF WORKAROUND
+
+ if (search_linked_namespaces) {
+ // if a library was not found - look into linked namespaces
+ // preserve current dlerror in the case it fails.
+ DlErrorRestorer dlerror_restorer;
+ LD_LOG(kLogDlopen, "find_library_internal(ns=%s, task=%s): Trying %zu linked namespaces",
+ ns->get_name(), task->get_name(), ns->linked_namespaces().size());
+ for (auto& linked_namespace : ns->linked_namespaces()) {
+ if (find_library_in_linked_namespace(linked_namespace, task)) {
+ if (task->get_soinfo() == nullptr) {
+ // try to load the library - once namespace boundary is crossed
+ // we need to load a library within separate load_group
+ // to avoid using symbols from foreign namespace while.
+ //
+ // However, actual linking is deferred until when the global group
+ // is fully identified and is applied to all namespaces.
+ // Otherwise, the libs in the linked namespace won't get symbols from
+ // the global group.
+ if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
+ LD_LOG(
+ kLogDlopen, "find_library_internal(ns=%s, task=%s): Found in linked namespace %s",
+ ns->get_name(), task->get_name(), linked_namespace.linked_namespace()->get_name());
+ return true;
+ }
+ } else {
+ // lib is already loaded
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static void soinfo_unload(soinfo* si);
+
+static void shuffle(std::vector<LoadTask*>* v) {
+ if (is_first_stage_init()) {
+ // arc4random* is not available in first stage init because /dev/random
+ // hasn't yet been created.
+ return;
+ }
+ for (size_t i = 0, size = v->size(); i < size; ++i) {
+ size_t n = size - i;
+ //size_t r = arc4random_uniform(n);
+ size_t r = rand() % n;
+ std::swap((*v)[n-1], (*v)[r]);
+ }
+}
+
+
+// add_as_children - add first-level loaded libraries (i.e. library_names[], but
+// not their transitive dependencies) as children of the start_with library.
+// This is false when find_libraries is called for dlopen(), when newly loaded
+// libraries must form a disjoint tree.
+bool find_libraries(android_namespace_t* ns,
+ soinfo* start_with,
+ const char* const library_names[],
+ size_t library_names_count,
+ soinfo* soinfos[],
+ std::vector<soinfo*>* ld_preloads,
+ size_t ld_preloads_count,
+ int rtld_flags,
+ const android_dlextinfo* extinfo,
+ bool add_as_children,
+ bool search_linked_namespaces,
+ std::vector<android_namespace_t*>* namespaces) {
+ // Step 0: prepare.
+ std::unordered_map<const soinfo*, ElfReader> readers_map;
+ LoadTaskList load_tasks;
+
+ for (size_t i = 0; i < library_names_count; ++i) {
+ const char* name = library_names[i];
+ load_tasks.push_back(LoadTask::create(name, start_with, ns, &readers_map));
+ }
+
+ // If soinfos array is null allocate one on stack.
+ // The array is needed in case of failure; for example
+ // when library_names[] = {libone.so, libtwo.so} and libone.so
+ // is loaded correctly but libtwo.so failed for some reason.
+ // In this case libone.so should be unloaded on return.
+ // See also implementation of failure_guard below.
+
+ if (soinfos == nullptr) {
+ size_t soinfos_size = sizeof(soinfo*)*library_names_count;
+ soinfos = reinterpret_cast<soinfo**>(alloca(soinfos_size));
+ memset(soinfos, 0, soinfos_size);
+ }
+
+ // list of libraries to link - see step 2.
+ size_t soinfos_count = 0;
+
+ auto scope_guard = android::base::make_scope_guard([&]() {
+ for (LoadTask* t : load_tasks) {
+ LoadTask::deleter(t);
+ }
+ });
+
+ ZipArchiveCache zip_archive_cache;
+
+ // Step 1: expand the list of load_tasks to include
+ // all DT_NEEDED libraries (do not load them just yet)
+ for (size_t i = 0; i<load_tasks.size(); ++i) {
+ LoadTask* task = load_tasks[i];
+ soinfo* needed_by = task->get_needed_by();
+
+ bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
+ task->set_extinfo(is_dt_needed ? nullptr : extinfo);
+ task->set_dt_needed(is_dt_needed);
+
+ LD_LOG(kLogDlopen, "find_libraries(ns=%s): task=%s, is_dt_needed=%d", ns->get_name(),
+ task->get_name(), is_dt_needed);
+
+ // Note: start from the namespace that is stored in the LoadTask. This namespace
+ // is different from the current namespace when the LoadTask is for a transitive
+ // dependency and the lib that created the LoadTask is not found in the
+ // current namespace but in one of the linked namespace.
+ if (!find_library_internal(const_cast<android_namespace_t*>(task->get_start_from()),
+ task,
+ &zip_archive_cache,
+ &load_tasks,
+ rtld_flags,
+ search_linked_namespaces || is_dt_needed)) {
+ return false;
+ }
+
+ soinfo* si = task->get_soinfo();
+
+ if (is_dt_needed) {
+ needed_by->add_child(si);
+ }
+
+ // When ld_preloads is not null, the first
+ // ld_preloads_count libs are in fact ld_preloads.
+ if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
+ ld_preloads->push_back(si);
+ }
+
+ if (soinfos_count < library_names_count) {
+ soinfos[soinfos_count++] = si;
+ }
+ }
+
+ // Step 2: Load libraries in random order (see b/24047022)
+ LoadTaskList load_list;
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ auto pred = [&](const LoadTask* t) {
+ return t->get_soinfo() == si;
+ };
+
+ if (!si->is_linked() &&
+ std::find_if(load_list.begin(), load_list.end(), pred) == load_list.end() ) {
+ load_list.push_back(task);
+ }
+ }
+ bool reserved_address_recursive = false;
+ if (extinfo) {
+ reserved_address_recursive = extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
+ }
+ if (!reserved_address_recursive) {
+ // Shuffle the load order in the normal case, but not if we are loading all
+ // the libraries to a reserved address range.
+ shuffle(&load_list);
+ }
+
+ // Set up address space parameters.
+ address_space_params extinfo_params, default_params;
+ size_t relro_fd_offset = 0;
+ if (extinfo) {
+ if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
+ extinfo_params.start_addr = extinfo->reserved_addr;
+ extinfo_params.reserved_size = extinfo->reserved_size;
+ extinfo_params.must_use_address = true;
+ } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
+ extinfo_params.start_addr = extinfo->reserved_addr;
+ extinfo_params.reserved_size = extinfo->reserved_size;
+ }
+ }
+
+ for (auto&& task : load_list) {
+ address_space_params* address_space =
+ (reserved_address_recursive || !task->is_dt_needed()) ? &extinfo_params : &default_params;
+ if (!task->load(address_space)) {
+ return false;
+ }
+ }
+
+ // Step 3: pre-link all DT_NEEDED libraries in breadth first order.
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ if (!si->is_linked() && !si->prelink_image()) {
+ return false;
+ }
+ register_soinfo_tls(si);
+ }
+
+ // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
+ // determined at step 3.
+
+ // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
+ // must be added to the global group
+ if (ld_preloads != nullptr) {
+ for (auto&& si : *ld_preloads) {
+ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
+ }
+ }
+
+ // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
+ // run. These will be the new member of the global group
+ soinfo_list_t new_global_group_members;
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+ new_global_group_members.push_back(si);
+ }
+ }
+
+ // Step 4-3: Add the new global group members to all the linked namespaces
+ if (namespaces != nullptr) {
+ for (auto linked_ns : *namespaces) {
+ for (auto si : new_global_group_members) {
+ if (si->get_primary_namespace() != linked_ns) {
+ linked_ns->add_soinfo(si);
+ si->add_secondary_namespace(linked_ns);
+ }
+ }
+ }
+ }
+
+ // Step 5: Collect roots of local_groups.
+ // Whenever needed_by->si link crosses a namespace boundary it forms its own local_group.
+ // Here we collect new roots to link them separately later on. Note that we need to avoid
+ // collecting duplicates. Also the order is important. They need to be linked in the same
+ // BFS order we link individual libraries.
+ std::vector<soinfo*> local_group_roots;
+ if (start_with != nullptr && add_as_children) {
+ local_group_roots.push_back(start_with);
+ } else {
+ CHECK(soinfos_count == 1);
+ local_group_roots.push_back(soinfos[0]);
+ }
+
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ soinfo* needed_by = task->get_needed_by();
+ bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
+ android_namespace_t* needed_by_ns =
+ is_dt_needed ? needed_by->get_primary_namespace() : ns;
+
+ if (!si->is_linked() && si->get_primary_namespace() != needed_by_ns) {
+ auto it = std::find(local_group_roots.begin(), local_group_roots.end(), si);
+ LD_LOG(kLogDlopen,
+ "Crossing namespace boundary (si=%s@%p, si_ns=%s@%p, needed_by=%s@%p, ns=%s@%p, needed_by_ns=%s@%p) adding to local_group_roots: %s",
+ si->get_realpath(),
+ si,
+ si->get_primary_namespace()->get_name(),
+ si->get_primary_namespace(),
+ needed_by == nullptr ? "(nullptr)" : needed_by->get_realpath(),
+ needed_by,
+ ns->get_name(),
+ ns,
+ needed_by_ns->get_name(),
+ needed_by_ns,
+ it == local_group_roots.end() ? "yes" : "no");
+
+ if (it == local_group_roots.end()) {
+ local_group_roots.push_back(si);
+ }
+ }
+ }
+
+ // Step 6: Link all local groups
+ for (auto root : local_group_roots) {
+ soinfo_list_t local_group;
+ android_namespace_t* local_group_ns = root->get_primary_namespace();
+
+ walk_dependencies_tree(root,
+ [&] (soinfo* si) {
+ if (local_group_ns->is_accessible(si)) {
+ local_group.push_back(si);
+ return kWalkContinue;
+ } else {
+ return kWalkSkip;
+ }
+ });
+
+ soinfo_list_t global_group = local_group_ns->get_global_group();
+ bool linked = local_group.visit([&](soinfo* si) {
+ // Even though local group may contain accessible soinfos from other namespaces
+ // we should avoid linking them (because if they are not linked -> they
+ // are in the local_group_roots and will be linked later).
+ if (!si->is_linked() && si->get_primary_namespace() == local_group_ns) {
+ const android_dlextinfo* link_extinfo = nullptr;
+ if (si == soinfos[0] || reserved_address_recursive) {
+ // Only forward extinfo for the first library unless the recursive
+ // flag is set.
+ link_extinfo = extinfo;
+ }
+ if (!si->link_image(global_group, local_group, link_extinfo, &relro_fd_offset) ||
+ !get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ if (!linked) {
+ return false;
+ }
+ }
+
+ // Step 7: Mark all load_tasks as linked and increment refcounts
+ // for references between load_groups (at this point it does not matter if
+ // referenced load_groups were loaded by previous dlopen or as part of this
+ // one on step 6)
+ if (start_with != nullptr && add_as_children) {
+ start_with->set_linked();
+ }
+
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ si->set_linked();
+ }
+
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ soinfo* needed_by = task->get_needed_by();
+ if (needed_by != nullptr &&
+ needed_by != start_with &&
+ needed_by->get_local_group_root() != si->get_local_group_root()) {
+ si->increment_ref_count();
+ }
+ }
+
+
+ return true;
+}
+
+static soinfo* find_library(android_namespace_t* ns,
+ const char* name, int rtld_flags,
+ const android_dlextinfo* extinfo,
+ soinfo* needed_by) {
+ soinfo* si = nullptr;
+
+ if (name == nullptr) {
+ si = nullptr;//solist_get_somain();
+ } else if (!find_libraries(ns,
+ needed_by,
+ &name,
+ 1,
+ &si,
+ nullptr,
+ 0,
+ rtld_flags,
+ extinfo,
+ false /* add_as_children */,
+ true /* search_linked_namespaces */)) {
+ if (si != nullptr) {
+ soinfo_unload(si);
+ }
+ return nullptr;
+ }
+
+ si->increment_ref_count();
+
+ return si;
+}
+
+static void soinfo_unload_impl(soinfo* root) {
+ ScopedTrace trace((std::string("unload ") + root->get_realpath()).c_str());
+ bool is_linked = root->is_linked();
+
+ if (!root->can_unload()) {
+ LD_LOG(kLogDlopen,
+ "... dlclose(root=\"%s\"@%p) ... not unloading - the load group is flagged with NODELETE",
+ root->get_realpath(),
+ root);
+ return;
+ }
+
+
+ soinfo_list_t unload_list;
+ unload_list.push_back(root);
+
+ soinfo_list_t local_unload_list;
+ soinfo_list_t external_unload_list;
+ soinfo* si = nullptr;
+
+ while ((si = unload_list.pop_front()) != nullptr) {
+ if (local_unload_list.contains(si)) {
+ continue;
+ }
+
+ local_unload_list.push_back(si);
+
+ if (si->has_min_version(0)) {
+ soinfo* child = nullptr;
+ while ((child = si->get_children().pop_front()) != nullptr) {
+ TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
+ child->get_realpath(), child);
+
+ child->get_parents().remove(si);
+
+ if (local_unload_list.contains(child)) {
+ continue;
+ } else if (child->is_linked() && child->get_local_group_root() != root) {
+ external_unload_list.push_back(child);
+ } else if (child->get_parents().empty()) {
+ unload_list.push_back(child);
+ }
+ }
+ } else {
+ async_safe_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
+ }
+ }
+
+ local_unload_list.for_each([](soinfo* si) {
+ LD_LOG(kLogDlopen,
+ "... dlclose: calling destructors for \"%s\"@%p ... ",
+ si->get_realpath(),
+ si);
+ si->call_destructors();
+ LD_LOG(kLogDlopen,
+ "... dlclose: calling destructors for \"%s\"@%p ... done",
+ si->get_realpath(),
+ si);
+ });
+
+ while ((si = local_unload_list.pop_front()) != nullptr) {
+ LD_LOG(kLogDlopen,
+ "... dlclose: unloading \"%s\"@%p ...",
+ si->get_realpath(),
+ si);
+ notify_gdb_of_unload(si);
+ unregister_soinfo_tls(si);
+ get_cfi_shadow()->BeforeUnload(si);
+ soinfo_free(si);
+ }
+
+ if (is_linked) {
+ while ((si = external_unload_list.pop_front()) != nullptr) {
+ LD_LOG(kLogDlopen,
+ "... dlclose: unloading external reference \"%s\"@%p ...",
+ si->get_realpath(),
+ si);
+ soinfo_unload(si);
+ }
+ } else {
+ LD_LOG(kLogDlopen,
+ "... dlclose: unload_si was not linked - not unloading external references ...");
+ }
+}
+
+static void soinfo_unload(soinfo* unload_si) {
+ // Note that the library can be loaded but not linked;
+ // in which case there is no root but we still need
+ // to walk the tree and unload soinfos involved.
+ //
+ // This happens on unsuccessful dlopen, when one of
+ // the DT_NEEDED libraries could not be linked/found.
+ bool is_linked = unload_si->is_linked();
+ soinfo* root = is_linked ? unload_si->get_local_group_root() : unload_si;
+
+ LD_LOG(kLogDlopen,
+ "... dlclose(realpath=\"%s\"@%p) ... load group root is \"%s\"@%p",
+ unload_si->get_realpath(),
+ unload_si,
+ root->get_realpath(),
+ root);
+
+
+ size_t ref_count = is_linked ? root->decrement_ref_count() : 0;
+ if (ref_count > 0) {
+ LD_LOG(kLogDlopen,
+ "... dlclose(root=\"%s\"@%p) ... not unloading - decrementing ref_count to %zd",
+ root->get_realpath(),
+ root,
+ ref_count);
+ return;
+ }
+
+ soinfo_unload_impl(root);
+}
+
+void increment_dso_handle_reference_counter(void* dso_handle) {
+ if (dso_handle == nullptr) {
+ return;
+ }
+
+ auto it = g_dso_handle_counters.find(dso_handle);
+ if (it != g_dso_handle_counters.end()) {
+ CHECK(++it->second != 0);
+ } else {
+ soinfo* si = find_containing_library(dso_handle);
+ if (si != nullptr) {
+ ProtectedDataGuard guard;
+ si->increment_ref_count();
+ } else {
+ async_safe_fatal(
+ "increment_dso_handle_reference_counter: Couldn't find soinfo by dso_handle=%p",
+ dso_handle);
+ }
+ g_dso_handle_counters[dso_handle] = 1U;
+ }
+}
+
+void decrement_dso_handle_reference_counter(void* dso_handle) {
+ if (dso_handle == nullptr) {
+ return;
+ }
+
+ auto it = g_dso_handle_counters.find(dso_handle);
+ CHECK(it != g_dso_handle_counters.end());
+ CHECK(it->second != 0);
+
+ if (--it->second == 0) {
+ soinfo* si = find_containing_library(dso_handle);
+ if (si != nullptr) {
+ ProtectedDataGuard guard;
+ soinfo_unload(si);
+ } else {
+ async_safe_fatal(
+ "decrement_dso_handle_reference_counter: Couldn't find soinfo by dso_handle=%p",
+ dso_handle);
+ }
+ g_dso_handle_counters.erase(it);
+ }
+}
+
+static std::string symbol_display_name(const char* sym_name, const char* sym_ver) {
+ if (sym_ver == nullptr) {
+ return sym_name;
+ }
+
+ return std::string(sym_name) + ", version " + sym_ver;
+}
+
+static android_namespace_t* get_caller_namespace(soinfo* caller) {
+ return caller != nullptr ? caller->get_primary_namespace() : g_anonymous_namespace;
+}
+
+void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
+ // Use basic string manipulation calls to avoid snprintf.
+ // snprintf indirectly calls pthread_getspecific to get the size of a buffer.
+ // When debug malloc is enabled, this call returns 0. This in turn causes
+ // snprintf to do nothing, which causes libraries to fail to load.
+ // See b/17302493 for further details.
+ // Once the above bug is fixed, this code can be modified to use
+ // snprintf again.
+ const auto& default_ld_paths = g_default_namespace->get_default_library_paths();
+
+ size_t required_size = 0;
+ for (const auto& path : default_ld_paths) {
+ required_size += path.size() + 1;
+ }
+
+ if (buffer_size < required_size) {
+ async_safe_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
+ "buffer len %zu, required len %zu", buffer_size, required_size);
+ }
+
+ char* end = buffer;
+ for (size_t i = 0; i < default_ld_paths.size(); ++i) {
+ if (i > 0) *end++ = ':';
+ end = stpcpy(end, default_ld_paths[i].c_str());
+ }
+}
+
+void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
+ parse_LD_LIBRARY_PATH(ld_library_path);
+}
+
+static std::string android_dlextinfo_to_string(const android_dlextinfo* info) {
+ if (info == nullptr) {
+ return "(null)";
+ }
+
+ return stringPrintf("[flags=0x%" PRIx64 ","
+ " reserved_addr=%p,"
+ " reserved_size=0x%zx,"
+ " relro_fd=%d,"
+ " library_fd=%d,"
+ " library_fd_offset=0x%" PRIx64 ","
+ " library_namespace=%s@%p]",
+ info->flags,
+ info->reserved_addr,
+ info->reserved_size,
+ info->relro_fd,
+ info->library_fd,
+ info->library_fd_offset,
+ (info->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0 ?
+ (info->library_namespace != nullptr ?
+ info->library_namespace->get_name() : "(null)") : "(n/a)",
+ (info->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0 ?
+ info->library_namespace : nullptr);
+}
+
+void* do_dlopen(const char* name, int flags,
+ const android_dlextinfo* extinfo,
+ const void* caller_addr) {
+ std::string trace_prefix = std::string("dlopen: ") + (name == nullptr ? "(nullptr)" : name);
+ ScopedTrace trace(trace_prefix.c_str());
+ ScopedTrace loading_trace((trace_prefix + " - loading and linking").c_str());
+ soinfo* const caller = find_containing_library(caller_addr);
+ android_namespace_t* ns = get_caller_namespace(caller);
+
+ LD_LOG(kLogDlopen,
+ "dlopen(name=\"%s\", flags=0x%x, extinfo=%s, caller=\"%s\", caller_ns=%s@%p, targetSdkVersion=%i) ...",
+ name,
+ flags,
+ android_dlextinfo_to_string(extinfo).c_str(),
+ caller == nullptr ? "(null)" : caller->get_realpath(),
+ ns == nullptr ? "(null)" : ns->get_name(),
+ ns,
+ get_application_target_sdk_version());
+
+ auto purge_guard = android::base::make_scope_guard([&]() { purge_unused_memory(); });
+
+ auto failure_guard = android::base::make_scope_guard(
+ [&]() { LD_LOG(kLogDlopen, "... dlopen failed: %s", linker_get_error_buffer()); });
+
+ if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
+ DL_ERR("invalid flags to dlopen: %x", flags);
+ return nullptr;
+ }
+
+ if (extinfo != nullptr) {
+ if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
+ DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
+ return nullptr;
+ }
+
+ if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
+ (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
+ DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "
+ "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
+ return nullptr;
+ }
+
+ if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {
+ if (extinfo->library_namespace == nullptr) {
+ DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");
+ return nullptr;
+ }
+ ns = extinfo->library_namespace;
+ }
+ }
+
+ // Workaround for dlopen(/system/lib/<soname>) when .so is in /apex. http://b/121248172
+ // The workaround works only when targetSdkVersion < Q.
+ std::string name_to_apex;
+ if (translateSystemPathToApexPath(name, &name_to_apex)) {
+ const char* new_name = name_to_apex.c_str();
+ LD_LOG(kLogDlopen, "dlopen considering translation from %s to APEX path %s",
+ name,
+ new_name);
+ // Some APEXs could be optionally disabled. Only translate the path
+ // when the old file is absent and the new file exists.
+ // TODO(b/124218500): Re-enable it once app compat issue is resolved
+ /*
+ if (file_exists(name)) {
+ LD_LOG(kLogDlopen, "dlopen %s exists, not translating", name);
+ } else
+ */
+ if (!file_exists(new_name)) {
+ LD_LOG(kLogDlopen, "dlopen %s does not exist, not translating",
+ new_name);
+ } else {
+ LD_LOG(kLogDlopen, "dlopen translation accepted: using %s", new_name);
+ name = new_name;
+ }
+ }
+ // End Workaround for dlopen(/system/lib/<soname>) when .so is in /apex.
+
+ std::string asan_name_holder;
+
+ const char* translated_name = name;
+ if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
+ char original_path[PATH_MAX];
+ if (realpath(name, original_path) != nullptr) {
+ asan_name_holder = std::string(kAsanLibDirPrefix) + original_path;
+ if (file_exists(asan_name_holder.c_str())) {
+ soinfo* si = nullptr;
+ if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
+ PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
+ asan_name_holder.c_str());
+ } else {
+ PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+ translated_name = asan_name_holder.c_str();
+ }
+ }
+ }
+ }
+
+ ProtectedDataGuard guard;
+ soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);
+ loading_trace.End();
+
+ if (si != nullptr) {
+ void* handle = si->to_handle();
+ LD_LOG(kLogDlopen,
+ "... dlopen calling constructors: realpath=\"%s\", soname=\"%s\", handle=%p",
+ si->get_realpath(), si->get_soname(), handle);
+ si->call_constructors();
+ failure_guard.Disable();
+ LD_LOG(kLogDlopen,
+ "... dlopen successful: realpath=\"%s\", soname=\"%s\", handle=%p",
+ si->get_realpath(), si->get_soname(), handle);
+ return handle;
+ }
+
+ return nullptr;
+}
+
+int do_dladdr(const void* addr, Dl_info* info) {
+ // Determine if this address can be found in any library currently mapped.
+ soinfo* si = find_containing_library(addr);
+ if (si == nullptr) {
+ return 0;
+ }
+
+ memset(info, 0, sizeof(Dl_info));
+
+ info->dli_fname = si->get_realpath();
+ // Address at which the shared object is loaded.
+ info->dli_fbase = reinterpret_cast<void*>(si->base);
+
+ // Determine if any symbol in the library contains the specified address.
+ ElfW(Sym)* sym = si->find_symbol_by_address(addr);
+ if (sym != nullptr) {
+ info->dli_sname = si->get_string(sym->st_name);
+ info->dli_saddr = reinterpret_cast<void*>(si->resolve_symbol_address(sym));
+ }
+
+ return 1;
+}
+
+static soinfo* soinfo_from_handle(void* handle) {
+ if ((reinterpret_cast<uintptr_t>(handle) & 1) != 0) {
+ auto it = g_soinfo_handles_map.find(reinterpret_cast<uintptr_t>(handle));
+ if (it == g_soinfo_handles_map.end()) {
+ return nullptr;
+ } else {
+ return it->second;
+ }
+ }
+
+ return static_cast<soinfo*>(handle);
+}
+
+bool do_dlsym(void* handle,
+ const char* sym_name,
+ const char* sym_ver,
+ const void* caller_addr,
+ void** symbol) {
+ ScopedTrace trace("dlsym");
+#if !defined(__LP64__)
+ if (handle == nullptr) {
+ DL_ERR("dlsym failed: library handle is null");
+ return false;
+ }
+#endif
+
+ soinfo* found = nullptr;
+ const ElfW(Sym)* sym = nullptr;
+ soinfo* caller = find_containing_library(caller_addr);
+ android_namespace_t* ns = get_caller_namespace(caller);
+ soinfo* si = nullptr;
+ if (handle != RTLD_DEFAULT && handle != RTLD_NEXT) {
+ si = soinfo_from_handle(handle);
+ }
+
+ LD_LOG(kLogDlsym,
+ "dlsym(handle=%p(\"%s\"), sym_name=\"%s\", sym_ver=\"%s\", caller=\"%s\", caller_ns=%s@%p) ...",
+ handle,
+ si != nullptr ? si->get_realpath() : "n/a",
+ sym_name,
+ sym_ver,
+ caller == nullptr ? "(null)" : caller->get_realpath(),
+ ns == nullptr ? "(null)" : ns->get_name(),
+ ns);
+
+ auto failure_guard = android::base::make_scope_guard(
+ [&]() { LD_LOG(kLogDlsym, "... dlsym failed: %s", linker_get_error_buffer()); });
+
+ if (sym_name == nullptr) {
+ DL_ERR("dlsym failed: symbol name is null");
+ return false;
+ }
+
+ version_info vi_instance;
+ version_info* vi = nullptr;
+
+ if (sym_ver != nullptr) {
+ vi_instance.name = sym_ver;
+ vi_instance.elf_hash = calculate_elf_hash(sym_ver);
+ vi = &vi_instance;
+ }
+
+ if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
+ sym = dlsym_linear_lookup(ns, sym_name, vi, &found, caller, handle);
+ } else {
+ if (si == nullptr) {
+ DL_ERR("dlsym failed: invalid handle: %p", handle);
+ return false;
+ }
+ sym = dlsym_handle_lookup(si, &found, sym_name, vi);
+ }
+
+ if (sym != nullptr) {
+ uint32_t bind = ELF_ST_BIND(sym->st_info);
+ uint32_t type = ELF_ST_TYPE(sym->st_info);
+
+ if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
+ if (type == STT_TLS) {
+ fprintf(stderr, "TLS relocations not yet implemented in libhybris");
+ abort();
+ // For a TLS symbol, dlsym returns the address of the current thread's
+ // copy of the symbol. This function may allocate a DTV and/or storage
+ // for the source TLS module. (Allocating a DTV isn't necessary if the
+ // symbol is part of static TLS, but it's simpler to reuse
+ // __tls_get_addr.)
+ soinfo_tls* tls_module = found->get_tls();
+ if (tls_module == nullptr) {
+ DL_ERR("TLS symbol \"%s\" in solib \"%s\" with no TLS segment",
+ sym_name, found->get_realpath());
+ return false;
+ }
+ const TlsIndex ti { tls_module->module_id, sym->st_value };
+ *symbol = TLS_GET_ADDR(&ti);
+ } else {
+#ifdef WANT_ARM_TRACING
+ switch(ELF_ST_TYPE(sym->st_info))
+ {
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ case STT_ARM_TFUNC:
+ *symbol = reinterpret_cast<void*>(_create_wrapper((char*)symbol, (void*)found->resolve_symbol_address(sym), WRAPPER_DYNHOOK));
+ default:
+ *symbol = reinterpret_cast<void*>(found->resolve_symbol_address(sym));
+ }
+#else
+ *symbol = reinterpret_cast<void*>(found->resolve_symbol_address(sym));
+#endif
+ }
+ failure_guard.Disable();
+ LD_LOG(kLogDlsym,
+ "... dlsym successful: sym_name=\"%s\", sym_ver=\"%s\", found in=\"%s\", address=%p",
+ sym_name, sym_ver, found->get_soname(), *symbol);
+ return true;
+ }
+
+ DL_ERR("symbol \"%s\" found but not global", symbol_display_name(sym_name, sym_ver).c_str());
+ return false;
+ }
+
+ DL_ERR_NO_PRINT("undefined symbol: %s", symbol_display_name(sym_name, sym_ver).c_str());
+ return false;
+}
+
+int do_dlclose(void* handle) {
+ ScopedTrace trace("dlclose");
+ ProtectedDataGuard guard;
+ soinfo* si = soinfo_from_handle(handle);
+ if (si == nullptr) {
+ DL_ERR("invalid handle: %p", handle);
+ return -1;
+ }
+
+ LD_LOG(kLogDlopen,
+ "dlclose(handle=%p, realpath=\"%s\"@%p) ...",
+ handle,
+ si->get_realpath(),
+ si);
+ soinfo_unload(si);
+ LD_LOG(kLogDlopen,
+ "dlclose(handle=%p) ... done",
+ handle);
+ return 0;
+}
+
+bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path) {
+ if (g_anonymous_namespace_initialized) {
+ DL_ERR("anonymous namespace has already been initialized.");
+ return false;
+ }
+
+ ProtectedDataGuard guard;
+
+ // create anonymous namespace
+ // When the caller is nullptr - create_namespace will take global group
+ // from the anonymous namespace, which is fine because anonymous namespace
+ // is still pointing to the default one.
+ android_namespace_t* anon_ns =
+ create_namespace(nullptr,
+ "(anonymous)",
+ nullptr,
+ library_search_path,
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr,
+ g_default_namespace);
+
+ if (anon_ns == nullptr) {
+ return false;
+ }
+
+ if (!link_namespaces(anon_ns, g_default_namespace, shared_lib_sonames)) {
+ return false;
+ }
+
+ g_anonymous_namespace = anon_ns;
+ g_anonymous_namespace_initialized = true;
+
+ return true;
+}
+
+static void add_soinfos_to_namespace(const soinfo_list_t& soinfos, android_namespace_t* ns) {
+ ns->add_soinfos(soinfos);
+ for (auto si : soinfos) {
+ si->add_secondary_namespace(ns);
+ }
+}
+
+android_namespace_t* create_namespace(const void* caller_addr,
+ const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ android_namespace_t* parent_namespace) {
+ if (parent_namespace == nullptr) {
+ // if parent_namespace is nullptr -> set it to the caller namespace
+ soinfo* caller_soinfo = find_containing_library(caller_addr);
+
+ parent_namespace = caller_soinfo != nullptr ?
+ caller_soinfo->get_primary_namespace() :
+ g_anonymous_namespace;
+ }
+
+ ProtectedDataGuard guard;
+ std::vector<std::string> ld_library_paths;
+ std::vector<std::string> default_library_paths;
+ std::vector<std::string> permitted_paths;
+
+ parse_path(ld_library_path, ":", &ld_library_paths);
+ parse_path(default_library_path, ":", &default_library_paths);
+ parse_path(permitted_when_isolated_path, ":", &permitted_paths);
+
+ android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
+ ns->set_name(name);
+ ns->set_isolated((type & ANDROID_NAMESPACE_TYPE_ISOLATED) != 0);
+ ns->set_greylist_enabled((type & ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED) != 0);
+
+ if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
+ // append parent namespace paths.
+ std::copy(parent_namespace->get_ld_library_paths().begin(),
+ parent_namespace->get_ld_library_paths().end(),
+ back_inserter(ld_library_paths));
+
+ std::copy(parent_namespace->get_default_library_paths().begin(),
+ parent_namespace->get_default_library_paths().end(),
+ back_inserter(default_library_paths));
+
+ std::copy(parent_namespace->get_permitted_paths().begin(),
+ parent_namespace->get_permitted_paths().end(),
+ back_inserter(permitted_paths));
+
+ // If shared - clone the parent namespace
+ add_soinfos_to_namespace(parent_namespace->soinfo_list(), ns);
+ // and copy parent namespace links
+ for (auto& link : parent_namespace->linked_namespaces()) {
+ ns->add_linked_namespace(link.linked_namespace(), link.shared_lib_sonames(),
+ link.allow_all_shared_libs());
+ }
+ } else {
+ // If not shared - copy only the shared group
+ add_soinfos_to_namespace(parent_namespace->get_shared_group(), ns);
+ }
+
+ ns->set_ld_library_paths(std::move(ld_library_paths));
+ ns->set_default_library_paths(std::move(default_library_paths));
+ ns->set_permitted_paths(std::move(permitted_paths));
+
+ return ns;
+}
+
+bool link_namespaces(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to,
+ const char* shared_lib_sonames) {
+ if (namespace_to == nullptr) {
+ namespace_to = g_default_namespace;
+ }
+
+ if (namespace_from == nullptr) {
+ DL_ERR("error linking namespaces: namespace_from is null.");
+ return false;
+ }
+
+ if (shared_lib_sonames == nullptr || shared_lib_sonames[0] == '\0') {
+ DL_ERR("error linking namespaces \"%s\"->\"%s\": the list of shared libraries is empty.",
+ namespace_from->get_name(), namespace_to->get_name());
+ return false;
+ }
+
+ auto sonames = split(shared_lib_sonames, ":");
+ std::unordered_set<std::string> sonames_set(sonames.begin(), sonames.end());
+
+ ProtectedDataGuard guard;
+ namespace_from->add_linked_namespace(namespace_to, sonames_set, false);
+
+ return true;
+}
+
+bool link_namespaces_all_libs(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to) {
+ if (namespace_from == nullptr) {
+ DL_ERR("error linking namespaces: namespace_from is null.");
+ return false;
+ }
+
+ if (namespace_to == nullptr) {
+ DL_ERR("error linking namespaces: namespace_to is null.");
+ return false;
+ }
+
+ ProtectedDataGuard guard;
+ namespace_from->add_linked_namespace(namespace_to, std::unordered_set<std::string>(), true);
+
+ return true;
+}
+
+ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
+ typedef ElfW(Addr) (*ifunc_resolver_t)(void);
+ ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr);
+ ElfW(Addr) ifunc_addr = ifunc_resolver();
+ TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p",
+ ifunc_resolver, reinterpret_cast<void*>(ifunc_addr));
+
+ return ifunc_addr;
+}
+
+const version_info* VersionTracker::get_version_info(ElfW(Versym) source_symver) const {
+ if (source_symver < 2 ||
+ source_symver >= version_infos.size() ||
+ version_infos[source_symver].name == nullptr) {
+ return nullptr;
+ }
+
+ return &version_infos[source_symver];
+}
+
+void VersionTracker::add_version_info(size_t source_index,
+ ElfW(Word) elf_hash,
+ const char* ver_name,
+ const soinfo* target_si) {
+ if (source_index >= version_infos.size()) {
+ version_infos.resize(source_index+1);
+ }
+
+ version_infos[source_index].elf_hash = elf_hash;
+ version_infos[source_index].name = ver_name;
+ version_infos[source_index].target_si = target_si;
+}
+
+bool VersionTracker::init_verneed(const soinfo* si_from) {
+ uintptr_t verneed_ptr = si_from->get_verneed_ptr();
+
+ if (verneed_ptr == 0) {
+ return true;
+ }
+
+ size_t verneed_cnt = si_from->get_verneed_cnt();
+
+ for (size_t i = 0, offset = 0; i<verneed_cnt; ++i) {
+ const ElfW(Verneed)* verneed = reinterpret_cast<ElfW(Verneed)*>(verneed_ptr + offset);
+ size_t vernaux_offset = offset + verneed->vn_aux;
+ offset += verneed->vn_next;
+
+ if (verneed->vn_version != 1) {
+ DL_ERR("unsupported verneed[%zd] vn_version: %d (expected 1)", i, verneed->vn_version);
+ return false;
+ }
+
+ const char* target_soname = si_from->get_string(verneed->vn_file);
+ // find it in dependencies
+ soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) {
+ return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
+ });
+
+ if (target_si == nullptr) {
+ DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"",
+ target_soname, i, si_from->get_realpath());
+ return false;
+ }
+
+ for (size_t j = 0; j<verneed->vn_cnt; ++j) {
+ const ElfW(Vernaux)* vernaux = reinterpret_cast<ElfW(Vernaux)*>(verneed_ptr + vernaux_offset);
+ vernaux_offset += vernaux->vna_next;
+
+ const ElfW(Word) elf_hash = vernaux->vna_hash;
+ const char* ver_name = si_from->get_string(vernaux->vna_name);
+ ElfW(Half) source_index = vernaux->vna_other;
+
+ add_version_info(source_index, elf_hash, ver_name, target_si);
+ }
+ }
+
+ return true;
+}
+
+template <typename F>
+static bool for_each_verdef(const soinfo* si, F functor) {
+ if (!si->has_min_version(2)) {
+ return true;
+ }
+
+ uintptr_t verdef_ptr = si->get_verdef_ptr();
+ if (verdef_ptr == 0) {
+ return true;
+ }
+
+ size_t offset = 0;
+
+ size_t verdef_cnt = si->get_verdef_cnt();
+ for (size_t i = 0; i<verdef_cnt; ++i) {
+ const ElfW(Verdef)* verdef = reinterpret_cast<ElfW(Verdef)*>(verdef_ptr + offset);
+ size_t verdaux_offset = offset + verdef->vd_aux;
+ offset += verdef->vd_next;
+
+ if (verdef->vd_version != 1) {
+ DL_ERR("unsupported verdef[%zd] vd_version: %d (expected 1) library: %s",
+ i, verdef->vd_version, si->get_realpath());
+ return false;
+ }
+
+ if ((verdef->vd_flags & VER_FLG_BASE) != 0) {
+ // "this is the version of the file itself. It must not be used for
+ // matching a symbol. It can be used to match references."
+ //
+ // http://www.akkadia.org/drepper/symbol-versioning
+ continue;
+ }
+
+ if (verdef->vd_cnt == 0) {
+ DL_ERR("invalid verdef[%zd] vd_cnt == 0 (version without a name)", i);
+ return false;
+ }
+
+ const ElfW(Verdaux)* verdaux = reinterpret_cast<ElfW(Verdaux)*>(verdef_ptr + verdaux_offset);
+
+ if (functor(i, verdef, verdaux) == true) {
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool find_verdef_version_index(const soinfo* si, const version_info* vi, ElfW(Versym)* versym) {
+ if (vi == nullptr) {
+ *versym = kVersymNotNeeded;
+ return true;
+ }
+
+ *versym = kVersymGlobal;
+
+ return for_each_verdef(si,
+ [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) {
+ if (verdef->vd_hash == vi->elf_hash &&
+ strcmp(vi->name, si->get_string(verdaux->vda_name)) == 0) {
+ *versym = verdef->vd_ndx;
+ return true;
+ }
+
+ return false;
+ }
+ );
+}
+
+bool VersionTracker::init_verdef(const soinfo* si_from) {
+ return for_each_verdef(si_from,
+ [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) {
+ add_version_info(verdef->vd_ndx, verdef->vd_hash,
+ si_from->get_string(verdaux->vda_name), si_from);
+ return false;
+ }
+ );
+}
+
+bool VersionTracker::init(const soinfo* si_from) {
+ if (!si_from->has_min_version(2)) {
+ return true;
+ }
+
+ return init_verneed(si_from) && init_verdef(si_from);
+}
+
+// TODO (dimitry): Methods below need to be moved out of soinfo
+// and in more isolated file in order minimize dependencies on
+// unnecessary object in the linker binary. Consider making them
+// independent from soinfo (?).
+bool soinfo::lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
+ const char* sym_name, const version_info** vi) {
+ const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
+ ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
+
+ if (sym_ver != VER_NDX_LOCAL && sym_ver != VER_NDX_GLOBAL) {
+ *vi = version_tracker.get_version_info(sym_ver);
+
+ if (*vi == nullptr) {
+ DL_ERR("cannot find verneed/verdef for version index=%d "
+ "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_realpath());
+ return false;
+ }
+ } else {
+ // there is no version info
+ *vi = nullptr;
+ }
+
+ return true;
+}
+
+void soinfo::apply_relr_reloc(ElfW(Addr) offset) {
+ ElfW(Addr) address = offset + load_bias;
+ *reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
+}
+
+// Process relocations in SHT_RELR section (experimental).
+// Details of the encoding are described in this post:
+// https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ
+bool soinfo::relocate_relr() {
+ ElfW(Relr)* begin = relr_;
+ ElfW(Relr)* end = relr_ + relr_count_;
+ constexpr size_t wordsize = sizeof(ElfW(Addr));
+
+ ElfW(Addr) base = 0;
+ for (ElfW(Relr)* current = begin; current < end; ++current) {
+ ElfW(Relr) entry = *current;
+ ElfW(Addr) offset;
+
+ if ((entry&1) == 0) {
+ // Even entry: encodes the offset for next relocation.
+ offset = static_cast<ElfW(Addr)>(entry);
+ apply_relr_reloc(offset);
+ // Set base offset for subsequent bitmap entries.
+ base = offset + wordsize;
+ continue;
+ }
+
+ // Odd entry: encodes bitmap for relocations starting at base.
+ offset = base;
+ while (entry != 0) {
+ entry >>= 1;
+ if ((entry&1) != 0) {
+ apply_relr_reloc(offset);
+ }
+ offset += wordsize;
+ }
+
+ // Advance base offset by 63 words for 64-bit platforms,
+ // or 31 words for 32-bit platforms.
+ base += (8*wordsize - 1) * wordsize;
+ }
+ return true;
+}
+
+#if !defined(__mips__)
+#if defined(USE_RELA)
+static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) {
+ return rela->r_addend;
+}
+#else
+static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
+ if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE ||
+ ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE ||
+ ELFW(R_TYPE)(rel->r_info) == R_GENERIC_TLS_DTPREL ||
+ ELFW(R_TYPE)(rel->r_info) == R_GENERIC_TLS_TPREL) {
+ return *reinterpret_cast<ElfW(Addr)*>(reloc_addr);
+ }
+ return 0;
+}
+#endif
+
+static bool is_tls_reloc(ElfW(Word) type) {
+ switch (type) {
+ case R_GENERIC_TLS_DTPMOD:
+ case R_GENERIC_TLS_DTPREL:
+ case R_GENERIC_TLS_TPREL:
+ case R_GENERIC_TLSDESC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+template<typename ElfRelIteratorT>
+bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
+ const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
+ const size_t tls_tp_base = 0/*__libc_shared_globals()->static_tls_layout.offset_thread_pointer()*/;
+ std::vector<std::pair<TlsDescriptor*, size_t>> deferred_tlsdesc_relocs;
+
+ for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
+ const auto rel = rel_iterator.next();
+ if (rel == nullptr) {
+ return false;
+ }
+
+ ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);
+ ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);
+
+ ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
+ ElfW(Addr) sym_addr = 0;
+ const char* sym_name = nullptr;
+ ElfW(Addr) addend = get_addend(rel, reloc);
+
+ DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
+ if (type == R_GENERIC_NONE) {
+ continue;
+ }
+
+ const ElfW(Sym)* s = nullptr;
+ soinfo* lsi = nullptr;
+
+ if (sym == 0) {
+ // By convention in ld.bfd and lld, an omitted symbol on a TLS relocation
+ // is a reference to the current module.
+ if (is_tls_reloc(type)) {
+ lsi = this;
+ }
+ } else if (ELF_ST_BIND(symtab_[sym].st_info) == STB_LOCAL && is_tls_reloc(type)) {
+ // In certain situations, the Gold linker accesses a TLS symbol using a
+ // relocation to an STB_LOCAL symbol in .dynsym of either STT_SECTION or
+ // STT_TLS type. Bionic doesn't support these relocations, so issue an
+ // error. References:
+ // - https://groups.google.com/d/topic/generic-abi/dJ4_Y78aQ2M/discussion
+ // - https://sourceware.org/bugzilla/show_bug.cgi?id=17699
+ s = &symtab_[sym];
+ sym_name = get_string(s->st_name);
+ DL_ERR("unexpected TLS reference to local symbol \"%s\": "
+ "sym type %d, rel type %u (idx %zu of \"%s\")",
+ sym_name, ELF_ST_TYPE(s->st_info), type, idx, get_realpath());
+ return false;
+ } else {
+ sym_name = get_string(symtab_[sym].st_name);
+ const version_info* vi = nullptr;
+
+ sym_addr = reinterpret_cast<ElfW(Addr)>(_get_hooked_symbol(sym_name, get_realpath()));
+
+ if (!sym_addr) {
+ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+ return false;
+ }
+
+ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ return false;
+ }
+ }
+#ifdef WANT_ARM_TRACING
+ else
+ {
+ // this will be slower.
+ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+ return false;
+ }
+
+ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ return false;
+ }
+
+ switch(ELF_ST_TYPE(s->st_info))
+ {
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ case STT_ARM_TFUNC:
+ sym_addr = (ElfW(Addr))_create_wrapper(sym_name, (void*)sym_addr, WRAPPER_HOOKED);
+ break;
+ }
+ }
+#endif
+
+ if (sym_addr == 0 && s == nullptr) {
+ // We only allow an undefined symbol if this is a weak reference...
+ s = &symtab_[sym];
+ if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
+ DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_realpath());
+ return false;
+ }
+
+ /* IHI0044C AAELF 4.5.1.1:
+
+ Libraries are not searched to resolve weak references.
+ It is not an error for a weak reference to remain unsatisfied.
+
+ During linking, the value of an undefined weak reference is:
+ - Zero if the relocation type is absolute
+ - The address of the place if the relocation is pc-relative
+ - The address of nominal base address if the relocation
+ type is base-relative.
+ */
+
+ switch (type) {
+ case R_GENERIC_JUMP_SLOT:
+ case R_GENERIC_GLOB_DAT:
+ case R_GENERIC_RELATIVE:
+ case R_GENERIC_IRELATIVE:
+ case R_GENERIC_TLS_DTPMOD:
+ case R_GENERIC_TLS_DTPREL:
+ case R_GENERIC_TLS_TPREL:
+ case R_GENERIC_TLSDESC:
+#if defined(__aarch64__)
+ case R_AARCH64_ABS64:
+ case R_AARCH64_ABS32:
+ case R_AARCH64_ABS16:
+#elif defined(__x86_64__)
+ case R_X86_64_32:
+ case R_X86_64_64:
+#elif defined(__arm__)
+ case R_ARM_ABS32:
+#elif defined(__i386__)
+ case R_386_32:
+#endif
+ /*
+ * The sym_addr was initialized to be zero above, or the relocation
+ * code below does not care about value of sym_addr.
+ * No need to do anything.
+ */
+ break;
+#if defined(__x86_64__)
+ case R_X86_64_PC32:
+ sym_addr = reloc;
+ break;
+#elif defined(__i386__)
+ case R_386_PC32:
+ sym_addr = reloc;
+ break;
+#endif
+ default:
+ DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
+ return false;
+ }
+ } else if (sym_addr == 0) { // We got a definition.
+#if !defined(__LP64__)
+ // When relocating dso with text_relocation .text segment is
+ // not executable. We need to restore elf flags before resolving
+ // STT_GNU_IFUNC symbol.
+ bool protect_segments = has_text_relocations &&
+ lsi == this &&
+ ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
+ if (protect_segments) {
+ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't protect segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+ if (is_tls_reloc(type)) {
+ fprintf(stderr, "TLS relocations not yet implemented in libhybris");
+ abort();
+ if (ELF_ST_TYPE(s->st_info) != STT_TLS) {
+ DL_ERR("reference to non-TLS symbol \"%s\" from TLS relocation in \"%s\"",
+ sym_name, get_realpath());
+ return false;
+ }
+ if (lsi->get_tls() == nullptr) {
+ DL_ERR("TLS relocation refers to symbol \"%s\" in solib \"%s\" with no TLS segment",
+ sym_name, lsi->get_realpath());
+ return false;
+ }
+ sym_addr = s->st_value;
+ } else {
+ if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
+ DL_ERR("reference to TLS symbol \"%s\" from non-TLS relocation in \"%s\"",
+ sym_name, get_realpath());
+ return false;
+ }
+#ifdef WANT_ARM_TRACING
+ switch(ELF_ST_TYPE(s->st_info))
+ {
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ case STT_ARM_TFUNC:
+ sym_addr = (ElfW(Addr))_create_wrapper(sym_name,
+ (void*)lsi->resolve_symbol_address(s), WRAPPER_UNHOOKED);
+ break;
+ default:
+ sym_addr = lsi->resolve_symbol_address(s);
+ break;
+ }
+#else
+ sym_addr = lsi->resolve_symbol_address(s);
+#endif
+ }
+#if !defined(__LP64__)
+ if (protect_segments) {
+ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't unprotect loadable segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+ }
+ count_relocation(kRelocSymbol);
+ }
+
+ switch (type) {
+ case R_GENERIC_JUMP_SLOT:
+ count_relocation(kRelocAbsolute);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n",
+ reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(sym_addr + addend), sym_name);
+
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
+ break;
+ case R_GENERIC_GLOB_DAT:
+ count_relocation(kRelocAbsolute);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n",
+ reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(sym_addr + addend), sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
+ break;
+ case R_GENERIC_RELATIVE:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n",
+ reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(load_bias + addend));
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
+ break;
+ case R_GENERIC_IRELATIVE:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
+ reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(load_bias + addend));
+ {
+#if !defined(__LP64__)
+ // When relocating dso with text_relocation .text segment is
+ // not executable. We need to restore elf flags for this
+ // particular call.
+ if (has_text_relocations) {
+ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't protect segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+ ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
+#if !defined(__LP64__)
+ // Unprotect it afterwards...
+ if (has_text_relocations) {
+ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't unprotect loadable segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
+ }
+ break;
+ case R_GENERIC_TLS_TPREL:
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ {
+ ElfW(Addr) tpoff = 0;
+ if (lsi == nullptr) {
+ // Unresolved weak relocation. Leave tpoff at 0 to resolve
+ // &weak_tls_symbol to __get_tls().
+ } else {
+ CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
+ const TlsModule& mod = get_tls_module(lsi->get_tls()->module_id);
+ if (mod.static_offset != SIZE_MAX) {
+ tpoff += mod.static_offset - tls_tp_base;
+ } else {
+ DL_ERR("TLS symbol \"%s\" in dlopened \"%s\" referenced from \"%s\" using IE access model",
+ sym_name, lsi->get_realpath(), get_realpath());
+ return false;
+ }
+ }
+ tpoff += sym_addr + addend;
+ TRACE_TYPE(RELO, "RELO TLS_TPREL %16p <- %16p %s\n",
+ reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(tpoff), sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = tpoff;
+ }
+#else
+ fprintf(stderr, "TLS relocations not yet implemented in libhybris");
+ abort();
+#endif
+ break;
+
+#if !defined(__aarch64__)
+ // Omit support for DTPMOD/DTPREL on arm64, at least until
+ // http://b/123385182 is fixed. arm64 uses TLSDESC instead.
+ case R_GENERIC_TLS_DTPMOD:
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ {
+ size_t module_id = 0;
+ if (lsi == nullptr) {
+ // Unresolved weak relocation. Evaluate the module ID to 0.
+ } else {
+ CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
+ module_id = lsi->get_tls()->module_id;
+ }
+ TRACE_TYPE(RELO, "RELO TLS_DTPMOD %16p <- %zu %s\n",
+ reinterpret_cast<void*>(reloc), module_id, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = module_id;
+ }
+ break;
+ case R_GENERIC_TLS_DTPREL:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO TLS_DTPREL %16p <- %16p %s\n",
+ reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(sym_addr + addend), sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
+#else
+ fprintf(stderr, "TLS relocations not yet implemented in libhybris");
+ abort();
+#endif
+ break;
+#endif // !defined(__aarch64__)
+
+#if defined(__aarch64__)
+ // Bionic currently only implements TLSDESC for arm64. This implementation should work with
+ // other architectures, as long as the resolver functions are implemented.
+ case R_GENERIC_TLSDESC:
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ {
+ TlsDescriptor* desc = reinterpret_cast<TlsDescriptor*>(reloc);
+ if (lsi == nullptr) {
+ // Unresolved weak relocation.
+ desc->func = tlsdesc_resolver_unresolved_weak;
+ desc->arg = addend;
+ TRACE_TYPE(RELO, "RELO TLSDESC %16p <- unresolved weak 0x%zx %s\n",
+ reinterpret_cast<void*>(reloc), static_cast<size_t>(addend), sym_name);
+ } else {
+ CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
+ size_t module_id = lsi->get_tls()->module_id;
+ const TlsModule& mod = get_tls_module(module_id);
+ if (mod.static_offset != SIZE_MAX) {
+ desc->func = tlsdesc_resolver_static;
+ desc->arg = mod.static_offset - tls_tp_base + sym_addr + addend;
+ TRACE_TYPE(RELO, "RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s\n",
+ reinterpret_cast<void*>(reloc), mod.static_offset, tls_tp_base,
+ static_cast<size_t>(sym_addr), static_cast<size_t>(addend), sym_name);
+ } else {
+ tlsdesc_args_.push_back({
+ .generation = mod.first_generation,
+ .index.module_id = module_id,
+ .index.offset = sym_addr + addend,
+ });
+ // Defer the TLSDESC relocation until the address of the TlsDynamicResolverArg object
+ // is finalized.
+ deferred_tlsdesc_relocs.push_back({ desc, tlsdesc_args_.size() - 1 });
+ const TlsDynamicResolverArg& desc_arg = tlsdesc_args_.back();
+ TRACE_TYPE(RELO, "RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
+ reinterpret_cast<void*>(reloc), desc_arg.generation,
+ desc_arg.index.module_id, desc_arg.index.offset, sym_name);
+ }
+ }
+ }
+#else
+ fprintf(stderr, "TLS relocations not yet implemented in libhybris");
+ abort();
+#endif
+ break;
+#endif // defined(__aarch64__)
+
+#if defined(__aarch64__)
+ case R_AARCH64_ABS64:
+ count_relocation(kRelocAbsolute);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n",
+ reloc, sym_addr + addend, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
+ break;
+ case R_AARCH64_ABS32:
+ count_relocation(kRelocAbsolute);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n",
+ reloc, sym_addr + addend, sym_name);
+ {
+ const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
+ const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
+ if ((min_value <= (sym_addr + addend)) &&
+ ((sym_addr + addend) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
+ } else {
+ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
+ sym_addr + addend, min_value, max_value);
+ return false;
+ }
+ }
+ break;
+ case R_AARCH64_ABS16:
+ count_relocation(kRelocAbsolute);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
+ reloc, sym_addr + addend, sym_name);
+ {
+ const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
+ const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
+ if ((min_value <= (sym_addr + addend)) &&
+ ((sym_addr + addend) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
+ } else {
+ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
+ sym_addr + addend, min_value, max_value);
+ return false;
+ }
+ }
+ break;
+ case R_AARCH64_PREL64:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n",
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
+ break;
+ case R_AARCH64_PREL32:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n",
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
+ {
+ const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
+ const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
+ if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
+ ((sym_addr + addend - rel->r_offset) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
+ } else {
+ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
+ sym_addr + addend - rel->r_offset, min_value, max_value);
+ return false;
+ }
+ }
+ break;
+ case R_AARCH64_PREL16:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n",
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
+ {
+ const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
+ const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
+ if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
+ ((sym_addr + addend - rel->r_offset) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
+ } else {
+ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
+ sym_addr + addend - rel->r_offset, min_value, max_value);
+ return false;
+ }
+ }
+ break;
+
+ case R_AARCH64_COPY:
+ /*
+ * ET_EXEC is not supported so this should not happen.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
+ *
+ * Section 4.6.11 "Dynamic relocations"
+ * R_AARCH64_COPY may only appear in executable objects where e_type is
+ * set to ET_EXEC.
+ */
+ DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_realpath());
+ return false;
+#elif defined(__x86_64__)
+ case R_X86_64_32:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
+ static_cast<size_t>(sym_addr), sym_name);
+ *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend;
+ break;
+ case R_X86_64_64:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
+ static_cast<size_t>(sym_addr), sym_name);
+ *reinterpret_cast<Elf64_Addr*>(reloc) = sym_addr + addend;
+ break;
+ case R_X86_64_PC32:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s",
+ static_cast<size_t>(reloc), static_cast<size_t>(sym_addr - reloc),
+ static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name);
+ *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend - reloc;
+ break;
+#elif defined(__arm__)
+ case R_ARM_ABS32:
+ count_relocation(kRelocAbsolute);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
+ break;
+ case R_ARM_REL32:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s",
+ reloc, sym_addr, rel->r_offset, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
+ break;
+ case R_ARM_COPY:
+ /*
+ * ET_EXEC is not supported so this should not happen.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+ *
+ * Section 4.6.1.10 "Dynamic relocations"
+ * R_ARM_COPY may only appear in executable objects where e_type is
+ * set to ET_EXEC.
+ */
+ DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath());
+ return false;
+#elif defined(__i386__)
+ case R_386_32:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
+ break;
+ case R_386_PC32:
+ count_relocation(kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s",
+ reloc, (sym_addr - reloc), sym_addr, reloc, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr - reloc);
+ break;
+#endif
+ default:
+ DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx);
+ return false;
+ }
+ }
+
+#if defined(__aarch64__)
+ // Bionic currently only implements TLSDESC for arm64.
+ for (const std::pair<TlsDescriptor*, size_t>& pair : deferred_tlsdesc_relocs) {
+ TlsDescriptor* desc = pair.first;
+ desc->func = tlsdesc_resolver_dynamic;
+ desc->arg = reinterpret_cast<size_t>(&tlsdesc_args_[pair.second]);
+ }
+#endif
+
+ return true;
+}
+#endif // !defined(__mips__)
+
+// An empty list of soinfos
+static soinfo_list_t g_empty_list;
+
+bool soinfo::prelink_image() {
+ /* Extract dynamic section */
+ ElfW(Word) dynamic_flags = 0;
+ phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);
+
+ /* We can't log anything until the linker is relocated */
+ bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
+ if (!relocating_linker) {
+ INFO("[ Linking \"%s\" ]", get_realpath());
+ DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
+ }
+
+ if (dynamic == nullptr) {
+ if (!relocating_linker) {
+ DL_ERR("missing PT_DYNAMIC in \"%s\"", get_realpath());
+ }
+ return false;
+ } else {
+ if (!relocating_linker) {
+ DEBUG("dynamic = %p", dynamic);
+ }
+ }
+
+#if defined(__arm__)
+ (void) phdr_table_get_arm_exidx(phdr, phnum, load_bias,
+ &ARM_exidx, &ARM_exidx_count);
+#endif
+
+ /*TlsSegment tls_segment;
+ if (__bionic_get_tls_segment(phdr, phnum, load_bias, &tls_segment)) {
+ if (!__bionic_check_tls_alignment(&tls_segment.alignment)) {
+ if (!relocating_linker) {
+ DL_ERR("TLS segment alignment in \"%s\" is not a power of 2: %zu",
+ get_realpath(), tls_segment.alignment);
+ }
+ return false;
+ }
+ tls_ = std::make_unique<soinfo_tls>();
+ tls_->segment = tls_segment;
+ }*/
+
+ // Extract useful information from dynamic section.
+ // Note that: "Except for the DT_NULL element at the end of the array,
+ // and the relative order of DT_NEEDED elements, entries may appear in any order."
+ //
+ // source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html
+ uint32_t needed_count = 0;
+ for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
+ DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
+ d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+ switch (d->d_tag) {
+ case DT_SONAME:
+ // this is parsed after we have strtab initialized (see below).
+ break;
+
+ case DT_HASH:
+ nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
+ nchain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
+ bucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
+ chain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4);
+ break;
+
+ case DT_GNU_HASH:
+ gnu_nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
+ // skip symndx
+ gnu_maskwords_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
+ gnu_shift2_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
+
+ gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
+ gnu_bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
+ // amend chain for symndx = header[1]
+ gnu_chain_ = gnu_bucket_ + gnu_nbucket_ -
+ reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
+
+ if (!powerof2(gnu_maskwords_)) {
+ DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two",
+ gnu_maskwords_, get_realpath());
+ return false;
+ }
+ --gnu_maskwords_;
+
+ flags_ |= FLAG_GNU_HASH;
+ break;
+
+ case DT_STRTAB:
+ strtab_ = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_STRSZ:
+ strtab_size_ = d->d_un.d_val;
+ break;
+
+ case DT_SYMTAB:
+ symtab_ = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_SYMENT:
+ if (d->d_un.d_val != sizeof(ElfW(Sym))) {
+ DL_ERR("invalid DT_SYMENT: %zd in \"%s\"",
+ static_cast<size_t>(d->d_un.d_val), get_realpath());
+ return false;
+ }
+ break;
+
+ case DT_PLTREL:
+#if defined(USE_RELA)
+ if (d->d_un.d_val != DT_RELA) {
+ DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_RELA", get_realpath());
+ return false;
+ }
+#else
+ if (d->d_un.d_val != DT_REL) {
+ DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_REL", get_realpath());
+ return false;
+ }
+#endif
+ break;
+
+ case DT_JMPREL:
+#if defined(USE_RELA)
+ plt_rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
+#else
+ plt_rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
+#endif
+ break;
+
+ case DT_PLTRELSZ:
+#if defined(USE_RELA)
+ plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
+#else
+ plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
+#endif
+ break;
+
+ case DT_PLTGOT:
+#if defined(__mips__)
+ // Used by mips and mips64.
+ plt_got_ = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
+#endif
+ // Ignore for other platforms... (because RTLD_LAZY is not supported)
+ break;
+
+ case DT_DEBUG:
+ // Set the DT_DEBUG entry to the address of _r_debug for GDB
+ // if the dynamic table is writable
+// FIXME: not working currently for N64
+// The flags for the LOAD and DYNAMIC program headers do not agree.
+// The LOAD section containing the dynamic table has been mapped as
+// read-only, but the DYNAMIC header claims it is writable.
+#if !(defined(__mips__) && defined(__LP64__))
+ if ((dynamic_flags & PF_W) != 0) {
+ d->d_un.d_val = reinterpret_cast<uintptr_t>(&_r_debug);
+ }
+#endif
+ break;
+#if defined(USE_RELA)
+ case DT_RELA:
+ rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_RELASZ:
+ rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
+ break;
+
+ case DT_ANDROID_RELA:
+ android_relocs_ = reinterpret_cast<uint8_t*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_ANDROID_RELASZ:
+ android_relocs_size_ = d->d_un.d_val;
+ break;
+
+ case DT_ANDROID_REL:
+ DL_ERR("unsupported DT_ANDROID_REL in \"%s\"", get_realpath());
+ return false;
+
+ case DT_ANDROID_RELSZ:
+ DL_ERR("unsupported DT_ANDROID_RELSZ in \"%s\"", get_realpath());
+ return false;
+
+ case DT_RELAENT:
+ if (d->d_un.d_val != sizeof(ElfW(Rela))) {
+ DL_ERR("invalid DT_RELAENT: %zd", static_cast<size_t>(d->d_un.d_val));
+ return false;
+ }
+ break;
+
+ // Ignored (see DT_RELCOUNT comments for details).
+ case DT_RELACOUNT:
+ break;
+
+ case DT_REL:
+ DL_ERR("unsupported DT_REL in \"%s\"", get_realpath());
+ return false;
+
+ case DT_RELSZ:
+ DL_ERR("unsupported DT_RELSZ in \"%s\"", get_realpath());
+ return false;
+
+#else
+ case DT_REL:
+ rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_RELSZ:
+ rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
+ break;
+
+ case DT_RELENT:
+ if (d->d_un.d_val != sizeof(ElfW(Rel))) {
+ DL_ERR("invalid DT_RELENT: %zd", static_cast<size_t>(d->d_un.d_val));
+ return false;
+ }
+ break;
+
+ case DT_ANDROID_REL:
+ android_relocs_ = reinterpret_cast<uint8_t*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_ANDROID_RELSZ:
+ android_relocs_size_ = d->d_un.d_val;
+ break;
+
+ case DT_ANDROID_RELA:
+ DL_ERR("unsupported DT_ANDROID_RELA in \"%s\"", get_realpath());
+ return false;
+
+ case DT_ANDROID_RELASZ:
+ DL_ERR("unsupported DT_ANDROID_RELASZ in \"%s\"", get_realpath());
+ return false;
+
+ // "Indicates that all RELATIVE relocations have been concatenated together,
+ // and specifies the RELATIVE relocation count."
+ //
+ // TODO: Spec also mentions that this can be used to optimize relocation process;
+ // Not currently used by bionic linker - ignored.
+ case DT_RELCOUNT:
+ break;
+
+ case DT_RELA:
+ DL_ERR("unsupported DT_RELA in \"%s\"", get_realpath());
+ return false;
+
+ case DT_RELASZ:
+ DL_ERR("unsupported DT_RELASZ in \"%s\"", get_realpath());
+ return false;
+
+#endif
+ case DT_RELR:
+ relr_ = reinterpret_cast<ElfW(Relr)*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_RELRSZ:
+ relr_count_ = d->d_un.d_val / sizeof(ElfW(Relr));
+ break;
+
+ case DT_RELRENT:
+ if (d->d_un.d_val != sizeof(ElfW(Relr))) {
+ DL_ERR("invalid DT_RELRENT: %zd", static_cast<size_t>(d->d_un.d_val));
+ return false;
+ }
+ break;
+
+ // Ignored (see DT_RELCOUNT comments for details).
+ case DT_RELRCOUNT:
+ break;
+
+ case DT_INIT:
+ init_func_ = reinterpret_cast<linker_ctor_function_t>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
+ break;
+
+ case DT_FINI:
+ fini_func_ = reinterpret_cast<linker_dtor_function_t>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
+ break;
+
+ case DT_INIT_ARRAY:
+ init_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
+ break;
+
+ case DT_INIT_ARRAYSZ:
+ init_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
+ break;
+
+ case DT_FINI_ARRAY:
+ fini_array_ = reinterpret_cast<linker_dtor_function_t*>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
+ break;
+
+ case DT_FINI_ARRAYSZ:
+ fini_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
+ break;
+
+ case DT_PREINIT_ARRAY:
+ preinit_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
+ break;
+
+ case DT_PREINIT_ARRAYSZ:
+ preinit_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
+ break;
+
+ case DT_TEXTREL:
+#if defined(__LP64__)
+ DL_ERR("\"%s\" has text relocations", get_realpath());
+ return false;
+#else
+ has_text_relocations = true;
+ break;
+#endif
+
+ case DT_SYMBOLIC:
+ has_DT_SYMBOLIC = true;
+ break;
+
+ case DT_NEEDED:
+ ++needed_count;
+ break;
+
+ case DT_FLAGS:
+ if (d->d_un.d_val & DF_TEXTREL) {
+#if defined(__LP64__)
+ DL_ERR("\"%s\" has text relocations", get_realpath());
+ return false;
+#else
+ has_text_relocations = true;
+#endif
+ }
+ if (d->d_un.d_val & DF_SYMBOLIC) {
+ has_DT_SYMBOLIC = true;
+ }
+ break;
+
+ case DT_FLAGS_1:
+ set_dt_flags_1(d->d_un.d_val);
+
+ if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) {
+ DL_WARN("Warning: \"%s\" has unsupported flags DT_FLAGS_1=%p "
+ "(ignoring unsupported flags)",
+ get_realpath(), reinterpret_cast<void*>(d->d_un.d_val));
+ }
+ break;
+#if defined(__mips__)
+ case DT_MIPS_RLD_MAP:
+ // Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB.
+ {
+ r_debug** dp = reinterpret_cast<r_debug**>(load_bias + d->d_un.d_ptr);
+ *dp = &_r_debug;
+ }
+ break;
+ case DT_MIPS_RLD_MAP_REL:
+ // Set the DT_MIPS_RLD_MAP_REL entry to the address of _r_debug for GDB.
+ {
+ r_debug** dp = reinterpret_cast<r_debug**>(
+ reinterpret_cast<ElfW(Addr)>(d) + d->d_un.d_val);
+ *dp = &_r_debug;
+ }
+ break;
+
+ case DT_MIPS_RLD_VERSION:
+ case DT_MIPS_FLAGS:
+ case DT_MIPS_BASE_ADDRESS:
+ case DT_MIPS_UNREFEXTNO:
+ break;
+
+ case DT_MIPS_SYMTABNO:
+ mips_symtabno_ = d->d_un.d_val;
+ break;
+
+ case DT_MIPS_LOCAL_GOTNO:
+ mips_local_gotno_ = d->d_un.d_val;
+ break;
+
+ case DT_MIPS_GOTSYM:
+ mips_gotsym_ = d->d_un.d_val;
+ break;
+#endif
+ // Ignored: "Its use has been superseded by the DF_BIND_NOW flag"
+ case DT_BIND_NOW:
+ break;
+
+ case DT_VERSYM:
+ versym_ = reinterpret_cast<ElfW(Versym)*>(load_bias + d->d_un.d_ptr);
+ break;
+
+ case DT_VERDEF:
+ verdef_ptr_ = load_bias + d->d_un.d_ptr;
+ break;
+ case DT_VERDEFNUM:
+ verdef_cnt_ = d->d_un.d_val;
+ break;
+
+ case DT_VERNEED:
+ verneed_ptr_ = load_bias + d->d_un.d_ptr;
+ break;
+
+ case DT_VERNEEDNUM:
+ verneed_cnt_ = d->d_un.d_val;
+ break;
+
+ case DT_RUNPATH:
+ // this is parsed after we have strtab initialized (see below).
+ break;
+
+ case DT_TLSDESC_GOT:
+ case DT_TLSDESC_PLT:
+ // These DT entries are used for lazy TLSDESC relocations. Bionic
+ // resolves everything eagerly, so these can be ignored.
+ break;
+
+ default:
+ if (!relocating_linker) {
+ const char* tag_name;
+ if (d->d_tag == DT_RPATH) {
+ tag_name = "DT_RPATH";
+ } else if (d->d_tag == DT_ENCODING) {
+ tag_name = "DT_ENCODING";
+ } else if (d->d_tag >= DT_LOOS && d->d_tag <= DT_HIOS) {
+ tag_name = "unknown OS-specific";
+ } else if (d->d_tag >= DT_LOPROC && d->d_tag <= DT_HIPROC) {
+ tag_name = "unknown processor-specific";
+ } else {
+ tag_name = "unknown";
+ }
+ DL_WARN("Warning: \"%s\" unused DT entry: %s (type %p arg %p) (ignoring)",
+ get_realpath(),
+ tag_name,
+ reinterpret_cast<void*>(d->d_tag),
+ reinterpret_cast<void*>(d->d_un.d_val));
+ }
+ break;
+ }
+ }
+
+#if defined(__mips__) && !defined(__LP64__)
+ if (!mips_check_and_adjust_fp_modes()) {
+ return false;
+ }
+#endif
+
+ DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
+ reinterpret_cast<void*>(base), strtab_, symtab_);
+
+ // Sanity checks.
+ if (relocating_linker && needed_count != 0) {
+ DL_WARN("linker cannot have DT_NEEDED dependencies on other libraries");
+ //return false;
+ }
+ if (nbucket_ == 0 && gnu_nbucket_ == 0) {
+ DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" "
+ "(new hash type from the future?)", get_realpath());
+ return false;
+ }
+ if (strtab_ == nullptr) {
+ DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath());
+ return false;
+ }
+ if (symtab_ == nullptr) {
+ DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());
+ return false;
+ }
+
+ // second pass - parse entries relying on strtab
+ for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
+ switch (d->d_tag) {
+ case DT_SONAME:
+ set_soname(get_string(d->d_un.d_val));
+ break;
+ case DT_RUNPATH:
+ set_dt_runpath(get_string(d->d_un.d_val));
+ break;
+ }
+ }
+
+ // Before M release linker was using basename in place of soname.
+ // In the case when dt_soname is absent some apps stop working
+ // because they can't find dt_needed library by soname.
+ // This workaround should keep them working. (Applies only
+ // for apps targeting sdk version < M.) Make an exception for
+ // the main executable and linker; they do not need to have dt_soname.
+ // TODO: >= O the linker doesn't need this workaround.
+ if (soname_ == nullptr &&
+ this != solist_get_somain() &&
+ (flags_ & FLAG_LINKER) == 0 &&
+ get_application_target_sdk_version() < __ANDROID_API_M__) {
+ soname_ = basename(realpath_.c_str());
+ DL_WARN_documented_change(__ANDROID_API_M__,
+ "missing-soname-enforced-for-api-level-23",
+ "\"%s\" has no DT_SONAME (will use %s instead)",
+ get_realpath(), soname_);
+
+ // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI
+ }
+ return true;
+}
+
+bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
+ const android_dlextinfo* extinfo, size_t* relro_fd_offset) {
+ if (is_image_linked()) {
+ // already linked.
+ return true;
+ }
+
+ local_group_root_ = local_group.front();
+ if (local_group_root_ == nullptr) {
+ local_group_root_ = this;
+ }
+
+ if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) {
+ target_sdk_version_ = get_application_target_sdk_version();
+ }
+
+ VersionTracker version_tracker;
+
+ if (!version_tracker.init(this)) {
+ return false;
+ }
+
+#if !defined(__LP64__)
+ if (has_text_relocations) {
+ // Fail if app is targeting M or above.
+ int app_target_api_level = get_application_target_sdk_version();
+ if (app_target_api_level >= __ANDROID_API_M__) {
+ DL_ERR_AND_LOG("\"%s\" has text relocations (https://android.googlesource.com/platform/"
+ "bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-"
+ "Enforced-for-API-level-23)", get_realpath());
+ return false;
+ }
+ // Make segments writable to allow text relocations to work properly. We will later call
+ // phdr_table_protect_segments() after all of them are applied.
+ DL_WARN_documented_change(__ANDROID_API_M__,
+ "Text-Relocations-Enforced-for-API-level-23",
+ "\"%s\" has text relocations",
+ get_realpath());
+ add_dlwarning(get_realpath(), "text relocations");
+ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't unprotect loadable segments for \"%s\": %s", get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+
+ if (android_relocs_ != nullptr) {
+ // check signature
+ if (android_relocs_size_ > 3 &&
+ android_relocs_[0] == 'A' &&
+ android_relocs_[1] == 'P' &&
+ android_relocs_[2] == 'S' &&
+ android_relocs_[3] == '2') {
+ DEBUG("[ android relocating %s ]", get_realpath());
+
+ bool relocated = false;
+ const uint8_t* packed_relocs = android_relocs_ + 4;
+ const size_t packed_relocs_size = android_relocs_size_ - 4;
+
+ relocated = relocate(
+ version_tracker,
+ packed_reloc_iterator<sleb128_decoder>(
+ sleb128_decoder(packed_relocs, packed_relocs_size)),
+ global_group, local_group);
+
+ if (!relocated) {
+ return false;
+ }
+ } else {
+ DL_ERR("bad android relocation header.");
+ return false;
+ }
+ }
+
+ if (relr_ != nullptr) {
+ DEBUG("[ relocating %s relr ]", get_realpath());
+ if (!relocate_relr()) {
+ return false;
+ }
+ }
+
+#if defined(USE_RELA)
+ if (rela_ != nullptr) {
+ DEBUG("[ relocating %s rela ]", get_realpath());
+ if (!relocate(version_tracker,
+ plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
+ return false;
+ }
+ }
+ if (plt_rela_ != nullptr) {
+ DEBUG("[ relocating %s plt rela ]", get_realpath());
+ if (!relocate(version_tracker,
+ plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
+ return false;
+ }
+ }
+#else
+ if (rel_ != nullptr) {
+ DEBUG("[ relocating %s rel ]", get_realpath());
+ if (!relocate(version_tracker,
+ plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
+ return false;
+ }
+ }
+ if (plt_rel_ != nullptr) {
+ DEBUG("[ relocating %s plt rel ]", get_realpath());
+ if (!relocate(version_tracker,
+ plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
+ return false;
+ }
+ }
+#endif
+
+#if defined(__mips__)
+ if (!mips_relocate_got(version_tracker, global_group, local_group)) {
+ return false;
+ }
+#endif
+
+ DEBUG("[ finished linking %s ]", get_realpath());
+
+#if !defined(__LP64__)
+ if (has_text_relocations) {
+ // All relocations are done, we can protect our segments back to read-only.
+ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't protect segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+
+ // We can also turn on GNU RELRO protection if we're not linking the dynamic linker
+ // itself --- it can't make system calls yet, and will have to call protect_relro later.
+ if (!is_linker() && !protect_relro()) {
+ return false;
+ }
+
+ /* Handle serializing/sharing the RELRO segment */
+ if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
+ if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
+ extinfo->relro_fd, relro_fd_offset) < 0) {
+ DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
+ if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
+ extinfo->relro_fd, relro_fd_offset) < 0) {
+ DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+
+ notify_gdb_of_load(this);
+ set_image_linked();
+ return true;
+}
+
+bool soinfo::protect_relro() {
+ if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+static std::vector<android_namespace_t*> init_default_namespace_no_config(bool is_asan) {
+ g_default_namespace->set_isolated(false);
+ auto default_ld_paths = is_asan ? kAsanDefaultLdPaths : kDefaultLdPaths;
+
+ char real_path[PATH_MAX];
+ std::vector<std::string> ld_default_paths;
+ for (size_t i = 0; default_ld_paths[i] != nullptr; ++i) {
+ if (realpath(default_ld_paths[i], real_path) != nullptr) {
+ ld_default_paths.push_back(real_path);
+ } else {
+ ld_default_paths.push_back(default_ld_paths[i]);
+ }
+ }
+
+ g_default_namespace->set_default_library_paths(std::move(ld_default_paths));
+
+ std::vector<android_namespace_t*> namespaces;
+ namespaces.push_back(g_default_namespace);
+ return namespaces;
+}
+
+// return /apex/<name>/etc/ld.config.txt from /apex/<name>/bin/<exec>
+static std::string get_ld_config_file_apex_path(const char* executable_path) {
+ std::vector<std::string> paths = split(executable_path, "/");
+ if (paths.size() == 5 && paths[1] == "apex" && paths[3] == "bin") {
+ return std::string("/apex/") + paths[2] + "/etc/ld.config.txt";
+ }
+ return "";
+}
+
+static std::string get_ld_config_file_vndk_path() {
+ /*if (android::base::GetBoolProperty("ro.vndk.lite", false)) {
+ return kLdConfigVndkLiteFilePath;
+ }*/
+
+ std::string ld_config_file_vndk = kLdConfigFilePath;
+ size_t insert_pos = ld_config_file_vndk.find_last_of('.');
+ if (insert_pos == std::string::npos) {
+ insert_pos = ld_config_file_vndk.length();
+ }
+ ld_config_file_vndk.insert(insert_pos, Config::get_vndk_version_string('.'));
+ return ld_config_file_vndk;
+}
+
+static std::string get_ld_config_file_path(const char* executable_path) {
+#ifdef USE_LD_CONFIG_FILE
+ // This is a debugging/testing only feature. Must not be available on
+ // production builds.
+ const char* ld_config_file_env = getenv("LD_CONFIG_FILE");
+ if (ld_config_file_env != nullptr && file_exists(ld_config_file_env)) {
+ return ld_config_file_env;
+ }
+#endif
+
+ std::string path = get_ld_config_file_apex_path(executable_path);
+ if (!path.empty()) {
+ if (file_exists(path.c_str())) {
+ return path;
+ }
+ DL_WARN("Warning: couldn't read config file \"%s\" for \"%s\"",
+ path.c_str(), executable_path);
+ }
+
+ path = kLdConfigArchFilePath;
+ if (file_exists(path.c_str())) {
+ return path;
+ }
+
+ path = get_ld_config_file_vndk_path();
+ if (file_exists(path.c_str())) {
+ return path;
+ }
+
+ return kLdConfigFilePath;
+}
+
+std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path) {
+ g_default_namespace->set_name("(default)");
+
+#if DISABLED_FOR_HYBRIS_SUPPORT
+ soinfo* somain = solist_get_somain();
+
+ const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
+ somain->load_bias);
+ const char* bname = (interp != nullptr) ? basename(interp) : nullptr;
+
+ g_is_asan = bname != nullptr &&
+ (strcmp(bname, "linker_asan") == 0 ||
+ strcmp(bname, "linker_asan64") == 0);
+#endif
+
+ const Config* config = nullptr;
+
+ std::string error_msg;
+
+ std::string ld_config_file_path = get_ld_config_file_path(executable_path);
+
+ INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
+ if (!Config::read_binary_config(ld_config_file_path.c_str(),
+ executable_path,
+ g_is_asan,
+ &config,
+ &error_msg)) {
+ if (!error_msg.empty()) {
+ DL_WARN("Warning: couldn't read \"%s\" for \"%s\" (using default configuration instead): %s",
+ ld_config_file_path.c_str(),
+ executable_path,
+ error_msg.c_str());
+ }
+ config = nullptr;
+ }
+
+ if (config == nullptr) {
+ return init_default_namespace_no_config(g_is_asan);
+ }
+
+ const auto& namespace_configs = config->namespace_configs();
+ std::unordered_map<std::string, android_namespace_t*> namespaces;
+
+ // 1. Initialize default namespace
+ const NamespaceConfig* default_ns_config = config->default_namespace_config();
+
+ g_default_namespace->set_isolated(default_ns_config->isolated());
+ g_default_namespace->set_default_library_paths(default_ns_config->search_paths());
+ g_default_namespace->set_permitted_paths(default_ns_config->permitted_paths());
+
+ namespaces[default_ns_config->name()] = g_default_namespace;
+ if (default_ns_config->visible()) {
+ g_exported_namespaces[default_ns_config->name()] = g_default_namespace;
+ }
+
+ // 2. Initialize other namespaces
+
+ for (auto& ns_config : namespace_configs) {
+ if (namespaces.find(ns_config->name()) != namespaces.end()) {
+ continue;
+ }
+
+ android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
+ ns->set_name(ns_config->name());
+ ns->set_isolated(ns_config->isolated());
+ ns->set_default_library_paths(ns_config->search_paths());
+ ns->set_permitted_paths(ns_config->permitted_paths());
+ ns->set_whitelisted_libs(ns_config->whitelisted_libs());
+
+ namespaces[ns_config->name()] = ns;
+ if (ns_config->visible()) {
+ g_exported_namespaces[ns_config->name()] = ns;
+ }
+ }
+
+ // 3. Establish links between namespaces
+ for (auto& ns_config : namespace_configs) {
+ auto it_from = namespaces.find(ns_config->name());
+ CHECK(it_from != namespaces.end());
+ android_namespace_t* namespace_from = it_from->second;
+ for (const NamespaceLinkConfig& ns_link : ns_config->links()) {
+ auto it_to = namespaces.find(ns_link.ns_name());
+ CHECK(it_to != namespaces.end());
+ android_namespace_t* namespace_to = it_to->second;
+ if (ns_link.allow_all_shared_libs()) {
+ link_namespaces_all_libs(namespace_from, namespace_to);
+ } else {
+ link_namespaces(namespace_from, namespace_to, ns_link.shared_libs().c_str());
+ }
+ }
+ }
+ // we can no longer rely on the fact that libdl.so is part of default namespace
+ // this is why we want to add ld-android.so to all namespaces from ld.config.txt
+//hybris we have no libdl soinfo
+// soinfo* ld_android_so = solist_get_head();
+
+ // we also need vdso to be available for all namespaces (if present)
+ soinfo* vdso = solist_get_vdso();
+ for (auto it : namespaces) {
+// hybris we have no libdl soinfo
+ // it.second->add_soinfo(ld_android_so);
+ if (vdso != nullptr) {
+ it.second->add_soinfo(vdso);
+ }
+ // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
+ }
+
+ set_application_target_sdk_version(config->target_sdk_version());
+
+ std::vector<android_namespace_t*> created_namespaces;
+ created_namespaces.reserve(namespaces.size());
+ for (const auto& kv : namespaces) {
+ created_namespaces.push_back(kv.second);
+ }
+ return created_namespaces;
+}
+
+// This function finds a namespace exported in ld.config.txt by its name.
+// A namespace can be exported by setting .visible property to true.
+android_namespace_t* get_exported_namespace(const char* name) {
+ if (name == nullptr) {
+ return nullptr;
+ }
+ auto it = g_exported_namespaces.find(std::string(name));
+ if (it == g_exported_namespaces.end()) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+void purge_unused_memory() {
+ // For now, we only purge the memory used by LoadTask because we know those
+ // are temporary objects.
+ //
+ // Purging other LinkerBlockAllocator hardly yields much because they hold
+ // information about namespaces and opened libraries, which are not freed
+ // when the control leaves the linker.
+ //
+ // Purging BionicAllocator may give us a few dirty pages back, but those pages
+ // would be already zeroed out, so they compress easily in ZRAM. Therefore,
+ // it is not worth munmap()'ing those pages.
+ TypeBasedAllocator<LoadTask>::purge();
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker.generic.map
^
|
@@ -0,0 +1,28 @@
+{
+ global:
+ __loader_dlopen;
+ __loader_dlclose;
+ __loader_dlsym;
+ __loader_dlerror;
+ __loader_dladdr;
+ __loader_android_update_LD_LIBRARY_PATH;
+ __loader_android_get_LD_LIBRARY_PATH;
+ __loader_dl_iterate_phdr;
+ __loader_android_dlopen_ext;
+ __loader_android_set_application_target_sdk_version;
+ __loader_android_get_application_target_sdk_version;
+ __loader_android_init_anonymous_namespace;
+ __loader_android_create_namespace;
+ __loader_dlvsym;
+ __loader_android_dlwarning;
+ __loader_cfi_fail;
+ __loader_android_link_namespaces;
+ __loader_android_link_namespaces_all_libs;
+ __loader_android_get_exported_namespace;
+ __loader_add_thread_local_dtor;
+ __loader_remove_thread_local_dtor;
+ __loader_shared_globals;
+ rtld_db_dlactivity;
+ local:
+ *;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker.h
^
|
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <dlfcn.h>
+#include <android/dlext.h>
+#include <elf.h>
+
+typedef Elf32_Word Elf32_Relr;
+typedef Elf64_Xword Elf64_Relr;
+
+
+#include <inttypes.h>
+#include <link.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "private/bionic_page.h"
+#include "linked_list.h"
+#include "linker_common_types.h"
+#include "linker_logger.h"
+#include "linker_soinfo.h"
+
+#include <string>
+#include <vector>
+
+#if defined(__LP64__)
+#define ELFW(what) ELF64_ ## what
+#else
+#define ELFW(what) ELF32_ ## what
+#endif
+
+// mips64 interprets Elf64_Rel structures' r_info field differently.
+// bionic (like other C libraries) has macros that assume regular ELF files,
+// but the dynamic linker needs to be able to load mips64 ELF files.
+#if defined(__mips__) && defined(__LP64__)
+#undef ELF64_R_SYM
+#undef ELF64_R_TYPE
+#undef ELF64_R_INFO
+#define ELF64_R_SYM(info) (((info) >> 0) & 0xffffffff)
+#define ELF64_R_SSYM(info) (((info) >> 32) & 0xff)
+#define ELF64_R_TYPE3(info) (((info) >> 40) & 0xff)
+#define ELF64_R_TYPE2(info) (((info) >> 48) & 0xff)
+#define ELF64_R_TYPE(info) (((info) >> 56) & 0xff)
+#endif
+
+#define SUPPORTED_DT_FLAGS_1 (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE | DF_1_PIE)
+
+// Class used construct version dependency graph.
+class VersionTracker {
+ public:
+ VersionTracker() = default;
+ bool init(const soinfo* si_from);
+
+ const version_info* get_version_info(ElfW(Versym) source_symver) const;
+ private:
+ bool init_verneed(const soinfo* si_from);
+ bool init_verdef(const soinfo* si_from);
+ void add_version_info(size_t source_index, ElfW(Word) elf_hash,
+ const char* ver_name, const soinfo* target_si);
+
+ std::vector<version_info> version_infos;
+
+ DISALLOW_COPY_AND_ASSIGN(VersionTracker);
+};
+
+bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
+ soinfo** si_found_in, const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group, const ElfW(Sym)** symbol);
+
+enum RelocationKind {
+ kRelocAbsolute = 0,
+ kRelocRelative,
+ kRelocCopy,
+ kRelocSymbol,
+ kRelocMax
+};
+
+void count_relocation(RelocationKind kind);
+
+soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si);
+
+soinfo* find_containing_library(const void* p);
+
+int open_executable(const char* path, off64_t* file_offset, std::string* realpath);
+
+void do_android_get_LD_LIBRARY_PATH(char*, size_t);
+void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
+void* do_dlopen(const char* name,
+ int flags,
+ const android_dlextinfo* extinfo,
+ const void* caller_addr);
+
+int do_dlclose(void* handle);
+
+int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
+
+#if defined(__arm__)
+_Unwind_Ptr do_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount);
+#endif
+
+bool do_dlsym(void* handle, const char* sym_name,
+ const char* sym_ver,
+ const void* caller_addr,
+ void** symbol);
+
+int do_dladdr(const void* addr, Dl_info* info);
+
+// void ___cfi_slowpath(uint64_t CallSiteTypeId, void *Ptr, void *Ret);
+// void ___cfi_slowpath_diag(uint64_t CallSiteTypeId, void *Ptr, void *DiagData, void *Ret);
+void ___cfi_fail(uint64_t CallSiteTypeId, void* Ptr, void *DiagData, void *Ret);
+
+void set_application_target_sdk_version(int target);
+int get_application_target_sdk_version();
+
+enum {
+ /* A regular namespace is the namespace with a custom search path that does
+ * not impose any restrictions on the location of native libraries.
+ */
+ ANDROID_NAMESPACE_TYPE_REGULAR = 0,
+
+ /* An isolated namespace requires all the libraries to be on the search path
+ * or under permitted_when_isolated_path. The search path is the union of
+ * ld_library_path and default_library_path.
+ */
+ ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+
+ /* The shared namespace clones the list of libraries of the caller namespace upon creation
+ * which means that they are shared between namespaces - the caller namespace and the new one
+ * will use the same copy of a library if it was loaded prior to android_create_namespace call.
+ *
+ * Note that libraries loaded after the namespace is created will not be shared.
+ *
+ * Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor
+ * permitted_path from the caller's namespace.
+ */
+ ANDROID_NAMESPACE_TYPE_SHARED = 2,
+
+ /* This flag instructs linker to enable grey-list workaround for the namespace.
+ * See http://b/26394120 for details.
+ */
+ ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+
+ ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+};
+
+bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path);
+android_namespace_t* create_namespace(const void* caller_addr,
+ const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ android_namespace_t* parent_namespace);
+
+bool link_namespaces(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to,
+ const char* shared_lib_sonames);
+
+bool link_namespaces_all_libs(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to);
+
+android_namespace_t* get_exported_namespace(const char* name);
+
+void increment_dso_handle_reference_counter(void* dso_handle);
+void decrement_dso_handle_reference_counter(void* dso_handle);
+
+void purge_unused_memory();
+
+struct address_space_params {
+ void* start_addr = nullptr;
+ size_t reserved_size = 0;
+ bool must_use_address = false;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_allocator.cpp
^
|
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_allocator.h"
+#include "linker_debug.h"
+#include "linker_utils.h"
+#include "linker.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <async_safe/log.h>
+
+#include <memory.h>
+
+#include "private/bionic_prctl.h"
+
+#include "hybris_compat.h"
+
+//
+// LinkerMemeoryAllocator is general purpose allocator
+// designed to provide the same functionality as the malloc/free/realloc
+// libc functions.
+//
+// On alloc:
+// If size is >= 1k allocator proxies malloc call directly to mmap
+// If size < 1k allocator uses SmallObjectAllocator for the size
+// rounded up to the nearest power of two.
+//
+// On free:
+//
+// For a pointer allocated using proxy-to-mmap allocator unmaps
+// the memory.
+//
+// For a pointer allocated using SmallObjectAllocator it adds
+// the block to free_blocks_list_. If the number of free pages reaches 2,
+// SmallObjectAllocator munmaps one of the pages keeping the other one
+// in reserve.
+
+static const char kSignature[4] = {'L', 'M', 'A', 1};
+
+static const size_t kSmallObjectMaxSize = 1 << kSmallObjectMaxSizeLog2;
+
+// This type is used for large allocations (with size >1k)
+static const uint32_t kLargeObject = 111;
+
+bool operator<(const small_object_page_record& one, const small_object_page_record& two) {
+ return one.page_addr < two.page_addr;
+}
+
+static inline uint16_t log2(size_t number) {
+ uint16_t result = 0;
+ number--;
+
+ while (number != 0) {
+ result++;
+ number >>= 1;
+ }
+
+ return result;
+}
+
+LinkerSmallObjectAllocator::LinkerSmallObjectAllocator(uint32_t type, size_t block_size)
+ : type_(type), block_size_(block_size), free_pages_cnt_(0), free_blocks_list_(nullptr) {}
+
+void* LinkerSmallObjectAllocator::alloc() {
+ CHECK(block_size_ != 0);
+
+ if (free_blocks_list_ == nullptr) {
+ alloc_page();
+ }
+
+ small_object_block_record* block_record = free_blocks_list_;
+ if (block_record->free_blocks_cnt > 1) {
+ small_object_block_record* next_free = reinterpret_cast<small_object_block_record*>(
+ reinterpret_cast<uint8_t*>(block_record) + block_size_);
+ next_free->next = block_record->next;
+ next_free->free_blocks_cnt = block_record->free_blocks_cnt - 1;
+ free_blocks_list_ = next_free;
+ } else {
+ free_blocks_list_ = block_record->next;
+ }
+
+ // bookkeeping...
+ auto page_record = find_page_record(block_record);
+
+ if (page_record->allocated_blocks_cnt == 0) {
+ free_pages_cnt_--;
+ }
+
+ page_record->free_blocks_cnt--;
+ page_record->allocated_blocks_cnt++;
+
+ memset(block_record, 0, block_size_);
+
+ return block_record;
+}
+
+void LinkerSmallObjectAllocator::free_page(linker_vector_t::iterator page_record) {
+ void* page_start = reinterpret_cast<void*>(page_record->page_addr);
+ void* page_end = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(page_start) + PAGE_SIZE);
+
+ while (free_blocks_list_ != nullptr &&
+ free_blocks_list_ > page_start &&
+ free_blocks_list_ < page_end) {
+ free_blocks_list_ = free_blocks_list_->next;
+ }
+
+ small_object_block_record* current = free_blocks_list_;
+
+ while (current != nullptr) {
+ while (current->next > page_start && current->next < page_end) {
+ current->next = current->next->next;
+ }
+
+ current = current->next;
+ }
+
+ munmap(page_start, PAGE_SIZE);
+ page_records_.erase(page_record);
+ free_pages_cnt_--;
+}
+
+void LinkerSmallObjectAllocator::free(void* ptr) {
+ auto page_record = find_page_record(ptr);
+
+ ssize_t offset = reinterpret_cast<uintptr_t>(ptr) - sizeof(page_info);
+
+ if (offset % block_size_ != 0) {
+ async_safe_fatal("invalid pointer: %p (block_size=%zd)", ptr, block_size_);
+ }
+
+ memset(ptr, 0, block_size_);
+ small_object_block_record* block_record = reinterpret_cast<small_object_block_record*>(ptr);
+
+ block_record->next = free_blocks_list_;
+ block_record->free_blocks_cnt = 1;
+
+ free_blocks_list_ = block_record;
+
+ page_record->free_blocks_cnt++;
+ page_record->allocated_blocks_cnt--;
+
+ if (page_record->allocated_blocks_cnt == 0) {
+ if (free_pages_cnt_++ > 1) {
+ // if we already have a free page - unmap this one.
+ free_page(page_record);
+ }
+ }
+}
+
+linker_vector_t::iterator LinkerSmallObjectAllocator::find_page_record(void* ptr) {
+ void* addr = reinterpret_cast<void*>(PAGE_START(reinterpret_cast<uintptr_t>(ptr)));
+ small_object_page_record boundary;
+ boundary.page_addr = addr;
+ linker_vector_t::iterator it = std::lower_bound(
+ page_records_.begin(), page_records_.end(), boundary);
+
+ if (it == page_records_.end() || it->page_addr != addr) {
+ // not found...
+ async_safe_fatal("page record for %p was not found (block_size=%zd)", ptr, block_size_);
+ }
+
+ return it;
+}
+
+void LinkerSmallObjectAllocator::create_page_record(void* page_addr, size_t free_blocks_cnt) {
+ small_object_page_record record;
+ record.page_addr = page_addr;
+ record.free_blocks_cnt = free_blocks_cnt;
+ record.allocated_blocks_cnt = 0;
+
+ linker_vector_t::iterator it = std::lower_bound(
+ page_records_.begin(), page_records_.end(), record);
+ page_records_.insert(it, record);
+}
+
+void LinkerSmallObjectAllocator::alloc_page() {
+ static_assert(sizeof(page_info) % 16 == 0,
+ "sizeof(page_info) is not multiple of 16");
+ void* map_ptr = mmap(nullptr, PAGE_SIZE,
+ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ if (map_ptr == MAP_FAILED) {
+ async_safe_fatal("mmap failed");
+ }
+
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, "linker_alloc_small_objects");
+
+ page_info* info = reinterpret_cast<page_info*>(map_ptr);
+ memcpy(info->signature, kSignature, sizeof(kSignature));
+ info->type = type_;
+ info->allocator_addr = this;
+
+ size_t free_blocks_cnt = (PAGE_SIZE - sizeof(page_info))/block_size_;
+
+ create_page_record(map_ptr, free_blocks_cnt);
+
+ small_object_block_record* first_block = reinterpret_cast<small_object_block_record*>(info + 1);
+
+ first_block->next = free_blocks_list_;
+ first_block->free_blocks_cnt = free_blocks_cnt;
+
+ free_blocks_list_ = first_block;
+}
+
+
+void LinkerMemoryAllocator::initialize_allocators() {
+ if (allocators_ != nullptr) {
+ return;
+ }
+
+ LinkerSmallObjectAllocator* allocators =
+ reinterpret_cast<LinkerSmallObjectAllocator*>(allocators_buf_);
+
+ for (size_t i = 0; i < kSmallObjectAllocatorsCount; ++i) {
+ uint32_t type = i + kSmallObjectMinSizeLog2;
+ new (allocators + i) LinkerSmallObjectAllocator(type, 1 << type);
+ }
+
+ allocators_ = allocators;
+}
+
+void* LinkerMemoryAllocator::alloc_mmap(size_t size) {
+ size_t allocated_size = PAGE_END(size + sizeof(page_info));
+ void* map_ptr = mmap(nullptr, allocated_size,
+ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+
+ if (map_ptr == MAP_FAILED) {
+ async_safe_fatal("mmap failed");
+ }
+
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob");
+
+ page_info* info = reinterpret_cast<page_info*>(map_ptr);
+ memcpy(info->signature, kSignature, sizeof(kSignature));
+ info->type = kLargeObject;
+ info->allocated_size = allocated_size;
+
+ return info + 1;
+}
+
+void* LinkerMemoryAllocator::alloc(size_t size) {
+ // treat alloc(0) as alloc(1)
+ if (size == 0) {
+ size = 1;
+ }
+
+ if (size > kSmallObjectMaxSize) {
+ return alloc_mmap(size);
+ }
+
+ uint16_t log2_size = log2(size);
+
+ if (log2_size < kSmallObjectMinSizeLog2) {
+ log2_size = kSmallObjectMinSizeLog2;
+ }
+
+ return get_small_object_allocator(log2_size)->alloc();
+}
+
+page_info* LinkerMemoryAllocator::get_page_info(void* ptr) {
+ page_info* info = reinterpret_cast<page_info*>(PAGE_START(reinterpret_cast<size_t>(ptr)));
+ if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) {
+ async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
+ }
+
+ return info;
+}
+
+void* LinkerMemoryAllocator::realloc(void* ptr, size_t size) {
+ if (ptr == nullptr) {
+ return alloc(size);
+ }
+
+ if (size == 0) {
+ free(ptr);
+ return nullptr;
+ }
+
+ page_info* info = get_page_info(ptr);
+
+ size_t old_size = 0;
+
+ if (info->type == kLargeObject) {
+ old_size = info->allocated_size - sizeof(page_info);
+ } else {
+ LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+ if (allocator != info->allocator_addr) {
+ async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
+ }
+
+ old_size = allocator->get_block_size();
+ }
+
+ if (old_size < size) {
+ void *result = alloc(size);
+ memcpy(result, ptr, old_size);
+ free(ptr);
+ return result;
+ }
+
+ return ptr;
+}
+
+void LinkerMemoryAllocator::free(void* ptr) {
+ if (ptr == nullptr) {
+ return;
+ }
+
+ page_info* info = get_page_info(ptr);
+
+ if (info->type == kLargeObject) {
+ munmap(info, info->allocated_size);
+ } else {
+ LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+ if (allocator != info->allocator_addr) {
+ async_safe_fatal("invalid pointer %p (invalid allocator address for the page)", ptr);
+ }
+
+ allocator->free(ptr);
+ }
+}
+
+LinkerSmallObjectAllocator* LinkerMemoryAllocator::get_small_object_allocator(uint32_t type) {
+ if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) {
+ async_safe_fatal("invalid type: %u", type);
+ }
+
+ initialize_allocators();
+ return &allocators_[type - kSmallObjectMinSizeLog2];
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_allocator.h
^
|
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __LINKER_ALLOCATOR_H
+#define __LINKER_ALLOCATOR_H
+
+#include <stdlib.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include <async_safe/log.h>
+
+#include "private/bionic_prctl.h"
+
+const uint32_t kSmallObjectMaxSizeLog2 = 10;
+const uint32_t kSmallObjectMinSizeLog2 = 4;
+const uint32_t kSmallObjectAllocatorsCount = kSmallObjectMaxSizeLog2 - kSmallObjectMinSizeLog2 + 1;
+
+class LinkerSmallObjectAllocator;
+
+// This structure is placed at the beginning of each addressable page
+// and has all information we need to find the corresponding memory allocator.
+struct page_info {
+ char signature[4];
+ uint32_t type;
+ union {
+ // we use allocated_size for large objects allocator
+ size_t allocated_size;
+ // and allocator_addr for small ones.
+ LinkerSmallObjectAllocator* allocator_addr;
+ };
+} __attribute__((aligned(16)));
+
+struct small_object_page_record {
+ void* page_addr;
+ size_t free_blocks_cnt;
+ size_t allocated_blocks_cnt;
+};
+
+// for lower_bound...
+bool operator<(const small_object_page_record& one, const small_object_page_record& two);
+
+struct small_object_block_record {
+ small_object_block_record* next;
+ size_t free_blocks_cnt;
+};
+
+// This is implementation for std::vector allocator
+template <typename T>
+class linker_vector_allocator {
+ public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ T* allocate(size_t n, const T* hint = nullptr) {
+ size_t size = n * sizeof(T);
+ void* ptr = mmap(const_cast<T*>(hint), size,
+ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ if (ptr == MAP_FAILED) {
+ // Spec says we need to throw std::bad_alloc here but because our
+ // code does not support exception handling anyways - we are going to abort.
+ async_safe_fatal("mmap failed");
+ }
+
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "linker_alloc_vector");
+
+ return reinterpret_cast<T*>(ptr);
+ }
+
+ void deallocate(T* ptr, size_t n) {
+ munmap(ptr, n * sizeof(T));
+ }
+};
+
+typedef
+ std::vector<small_object_page_record, linker_vector_allocator<small_object_page_record>>
+ linker_vector_t;
+
+
+class LinkerSmallObjectAllocator {
+ public:
+ LinkerSmallObjectAllocator(uint32_t type, size_t block_size);
+ void* alloc();
+ void free(void* ptr);
+
+ size_t get_block_size() const { return block_size_; }
+ private:
+ void alloc_page();
+ void free_page(linker_vector_t::iterator page_record);
+ linker_vector_t::iterator find_page_record(void* ptr);
+ void create_page_record(void* page_addr, size_t free_blocks_cnt);
+
+ uint32_t type_;
+ size_t block_size_;
+
+ size_t free_pages_cnt_;
+ small_object_block_record* free_blocks_list_;
+
+ // sorted vector of page records
+ linker_vector_t page_records_;
+};
+
+class LinkerMemoryAllocator {
+ public:
+ constexpr LinkerMemoryAllocator() : allocators_(nullptr), allocators_buf_() {}
+ void* alloc(size_t size);
+
+ // Note that this implementation of realloc never shrinks allocation
+ void* realloc(void* ptr, size_t size);
+ void free(void* ptr);
+ private:
+ void* alloc_mmap(size_t size);
+ page_info* get_page_info(void* ptr);
+ LinkerSmallObjectAllocator* get_small_object_allocator(uint32_t type);
+ void initialize_allocators();
+
+ LinkerSmallObjectAllocator* allocators_;
+ uint8_t allocators_buf_[sizeof(LinkerSmallObjectAllocator)*kSmallObjectAllocatorsCount];
+};
+
+
+#endif /* __LINKER_ALLOCATOR_H */
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_block_allocator.cpp
^
|
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_block_allocator.h"
+#include <inttypes.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#include "private/bionic_prctl.h"
+
+#include "hybris_compat.h"
+
+static constexpr size_t kAllocateSize = PAGE_SIZE * 100;
+static_assert(kAllocateSize % PAGE_SIZE == 0, "Invalid kAllocateSize.");
+
+// the multiplier should be power of 2
+static constexpr size_t round_up(size_t size, size_t multiplier) {
+ return (size + (multiplier - 1)) & ~(multiplier-1);
+}
+
+struct LinkerBlockAllocatorPage {
+ LinkerBlockAllocatorPage* next;
+ uint8_t bytes[kAllocateSize - 16] __attribute__((aligned(16)));
+};
+
+struct FreeBlockInfo {
+ void* next_block;
+ size_t num_free_blocks;
+};
+
+LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size)
+ : block_size_(
+ round_up(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size, 16)),
+ page_list_(nullptr),
+ free_block_list_(nullptr),
+ allocated_(0)
+{}
+
+void* LinkerBlockAllocator::alloc() {
+ if (free_block_list_ == nullptr) {
+ create_new_page();
+ }
+
+ FreeBlockInfo* block_info = reinterpret_cast<FreeBlockInfo*>(free_block_list_);
+ if (block_info->num_free_blocks > 1) {
+ FreeBlockInfo* next_block_info = reinterpret_cast<FreeBlockInfo*>(
+ reinterpret_cast<char*>(free_block_list_) + block_size_);
+ next_block_info->next_block = block_info->next_block;
+ next_block_info->num_free_blocks = block_info->num_free_blocks - 1;
+ free_block_list_ = next_block_info;
+ } else {
+ free_block_list_ = block_info->next_block;
+ }
+
+ memset(block_info, 0, block_size_);
+
+ ++allocated_;
+
+ return block_info;
+}
+
+void LinkerBlockAllocator::free(void* block) {
+ if (block == nullptr) {
+ return;
+ }
+
+ LinkerBlockAllocatorPage* page = find_page(block);
+
+ if (page == nullptr) {
+ abort();
+ }
+
+ ssize_t offset = reinterpret_cast<uint8_t*>(block) - page->bytes;
+
+ if (offset % block_size_ != 0) {
+ abort();
+ }
+
+ memset(block, 0, block_size_);
+
+ FreeBlockInfo* block_info = reinterpret_cast<FreeBlockInfo*>(block);
+
+ block_info->next_block = free_block_list_;
+ block_info->num_free_blocks = 1;
+
+ free_block_list_ = block_info;
+
+ --allocated_;
+}
+
+void LinkerBlockAllocator::protect_all(int prot) {
+ for (LinkerBlockAllocatorPage* page = page_list_; page != nullptr; page = page->next) {
+ if (mprotect(page, kAllocateSize, prot) == -1) {
+ abort();
+ }
+ }
+}
+
+void LinkerBlockAllocator::create_new_page() {
+ static_assert(sizeof(LinkerBlockAllocatorPage) == kAllocateSize,
+ "Invalid sizeof(LinkerBlockAllocatorPage)");
+
+ LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>(
+ mmap(nullptr, kAllocateSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
+
+ if (page == MAP_FAILED) {
+ abort(); // oom
+ }
+
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, kAllocateSize, "linker_alloc");
+
+ FreeBlockInfo* first_block = reinterpret_cast<FreeBlockInfo*>(page->bytes);
+ first_block->next_block = free_block_list_;
+ first_block->num_free_blocks = sizeof(page->bytes) / block_size_;
+
+ free_block_list_ = first_block;
+
+ page->next = page_list_;
+ page_list_ = page;
+}
+
+LinkerBlockAllocatorPage* LinkerBlockAllocator::find_page(void* block) {
+ if (block == nullptr) {
+ abort();
+ }
+
+ LinkerBlockAllocatorPage* page = page_list_;
+ while (page != nullptr) {
+ const uint8_t* page_ptr = reinterpret_cast<const uint8_t*>(page);
+ if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + kAllocateSize)) {
+ return page;
+ }
+
+ page = page->next;
+ }
+
+ abort();
+}
+
+void LinkerBlockAllocator::purge() {
+ if (allocated_) {
+ return;
+ }
+
+ LinkerBlockAllocatorPage* page = page_list_;
+ while (page) {
+ LinkerBlockAllocatorPage* next = page->next;
+ munmap(page, kAllocateSize);
+ page = next;
+ }
+ page_list_ = nullptr;
+ free_block_list_ = nullptr;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_block_allocator.h
^
|
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <android-base/macros.h>
+
+struct LinkerBlockAllocatorPage;
+
+/*
+ * This class is a non-template version of the LinkerTypeAllocator
+ * It keeps code inside .cpp file by keeping the interface
+ * template-free.
+ *
+ * Please use LinkerTypeAllocator<type> where possible (everywhere).
+ */
+class LinkerBlockAllocator {
+ public:
+ explicit LinkerBlockAllocator(size_t block_size);
+
+ void* alloc();
+ void free(void* block);
+ void protect_all(int prot);
+
+ // Purge all pages if all previously allocated blocks have been freed.
+ void purge();
+
+ private:
+ void create_new_page();
+ LinkerBlockAllocatorPage* find_page(void* block);
+
+ size_t block_size_;
+ LinkerBlockAllocatorPage* page_list_;
+ void* free_block_list_;
+ size_t allocated_;
+
+ DISALLOW_COPY_AND_ASSIGN(LinkerBlockAllocator);
+};
+
+/*
+ * A simple allocator for the dynamic linker. An allocator allocates instances
+ * of a single fixed-size type. Allocations are backed by page-sized private
+ * anonymous mmaps.
+ *
+ * The differences between this allocator and BionicAllocator are:
+ * 1. This allocator manages space more efficiently. BionicAllocator operates in
+ * power-of-two sized blocks up to 1k, when this implementation splits the
+ * page to aligned size of structure; For example for structures with size
+ * 513 this allocator will use 516 (520 for lp64) bytes of data where
+ * generalized implementation is going to use 1024 sized blocks.
+ *
+ * 2. This allocator does not munmap allocated memory, where BionicAllocator does.
+ *
+ * 3. This allocator provides mprotect services to the user, where BionicAllocator
+ * always treats its memory as READ|WRITE.
+ */
+template<typename T>
+class LinkerTypeAllocator {
+ public:
+ LinkerTypeAllocator() : block_allocator_(sizeof(T)) {}
+ T* alloc() { return reinterpret_cast<T*>(block_allocator_.alloc()); }
+ void free(T* t) { block_allocator_.free(t); }
+ void protect_all(int prot) { block_allocator_.protect_all(prot); }
+ private:
+ LinkerBlockAllocator block_allocator_;
+ DISALLOW_COPY_AND_ASSIGN(LinkerTypeAllocator);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_block_allocator_test.cpp
^
|
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <gtest/gtest.h>
+
+#include "linker_block_allocator.h"
+
+#include <unistd.h>
+
+namespace {
+
+struct test_struct_nominal {
+ void* pointer;
+ ssize_t value;
+};
+
+/*
+ * this one has size below allocator cap which is 2*sizeof(void*)
+ */
+struct test_struct_small {
+ char dummy_str[5];
+};
+
+/*
+ * 1009 byte struct (1009 is prime)
+ */
+struct test_struct_larger {
+ char dummy_str[1009];
+};
+
+static size_t kPageSize = sysconf(_SC_PAGE_SIZE);
+};
+
+TEST(linker_allocator, test_nominal) {
+ LinkerTypeAllocator<test_struct_nominal> allocator;
+
+ test_struct_nominal* ptr1 = allocator.alloc();
+ ASSERT_TRUE(ptr1 != nullptr);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16);
+ test_struct_nominal* ptr2 = allocator.alloc();
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16);
+ ASSERT_TRUE(ptr2 != nullptr);
+ // they should be next to each other.
+ ASSERT_EQ(reinterpret_cast<uint8_t*>(ptr1)+16, reinterpret_cast<uint8_t*>(ptr2));
+
+ ptr1->value = 42;
+
+ allocator.free(ptr1);
+ allocator.free(ptr2);
+}
+
+TEST(linker_allocator, test_small) {
+ LinkerTypeAllocator<test_struct_small> allocator;
+
+ char* ptr1 = reinterpret_cast<char*>(allocator.alloc());
+ char* ptr2 = reinterpret_cast<char*>(allocator.alloc());
+
+ ASSERT_TRUE(ptr1 != nullptr);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16);
+ ASSERT_TRUE(ptr2 != nullptr);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16);
+ ASSERT_EQ(ptr1+16, ptr2); // aligned to 16
+}
+
+TEST(linker_allocator, test_larger) {
+ LinkerTypeAllocator<test_struct_larger> allocator;
+
+ test_struct_larger* ptr1 = allocator.alloc();
+ test_struct_larger* ptr2 = allocator.alloc();
+
+ ASSERT_TRUE(ptr1 != nullptr);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16);
+ ASSERT_TRUE(ptr2 != nullptr);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16);
+
+ ASSERT_EQ(reinterpret_cast<uint8_t*>(ptr1) + 1024, reinterpret_cast<uint8_t*>(ptr2));
+
+ // lets allocate until we reach next page.
+ size_t n = kPageSize/sizeof(test_struct_larger) + 1 - 2;
+
+ for (size_t i=0; i<n; ++i) {
+ ASSERT_TRUE(allocator.alloc() != nullptr);
+ }
+
+ test_struct_larger* ptr_to_free = allocator.alloc();
+ ASSERT_TRUE(ptr_to_free != nullptr);
+ allocator.free(ptr1);
+}
+
+static void protect_all() {
+ LinkerTypeAllocator<test_struct_larger> allocator;
+
+ // number of allocs to reach the end of first page
+ size_t n = kPageSize/sizeof(test_struct_larger) - 1;
+ test_struct_larger* page1_ptr = allocator.alloc();
+
+ for (size_t i=0; i<n; ++i) {
+ allocator.alloc();
+ }
+
+ test_struct_larger* page2_ptr = allocator.alloc();
+ allocator.protect_all(PROT_READ);
+ allocator.protect_all(PROT_READ | PROT_WRITE);
+ // check access
+ page2_ptr->dummy_str[23] = 27;
+ page1_ptr->dummy_str[13] = 11;
+
+ allocator.protect_all(PROT_READ);
+ fprintf(stderr, "trying to access protected page");
+
+ // this should result in segmentation fault
+ page1_ptr->dummy_str[11] = 7;
+}
+
+TEST(linker_allocator, test_protect) {
+ testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(protect_all(), testing::KilledBySignal(SIGSEGV), "trying to access protected page");
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_cfi.cpp
^
|
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_cfi.h"
+
+#include "linker_debug.h"
+#include "linker_globals.h"
+#include "private/bionic_page.h"
+
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <cstdint>
+
+#include "private/bionic_prctl.h"
+
+// Update shadow without making it writable by preparing the data on the side and mremap-ing it in
+// place.
+class ShadowWrite {
+ char* shadow_start;
+ char* shadow_end;
+ char* aligned_start;
+ char* aligned_end;
+ char* tmp_start;
+
+ public:
+ ShadowWrite(uint16_t* s, uint16_t* e) {
+ shadow_start = reinterpret_cast<char*>(s);
+ shadow_end = reinterpret_cast<char*>(e);
+ aligned_start = reinterpret_cast<char*>(PAGE_START(reinterpret_cast<uintptr_t>(shadow_start)));
+ aligned_end = reinterpret_cast<char*>(PAGE_END(reinterpret_cast<uintptr_t>(shadow_end)));
+ tmp_start =
+ reinterpret_cast<char*>(mmap(nullptr, aligned_end - aligned_start, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+ CHECK(tmp_start != MAP_FAILED);
+ memcpy(tmp_start, aligned_start, shadow_start - aligned_start);
+ memcpy(tmp_start + (shadow_end - aligned_start), shadow_end, aligned_end - shadow_end);
+ }
+
+ uint16_t* begin() {
+ return reinterpret_cast<uint16_t*>(tmp_start + (shadow_start - aligned_start));
+ }
+
+ uint16_t* end() {
+ return reinterpret_cast<uint16_t*>(tmp_start + (shadow_end - aligned_start));
+ }
+
+ ~ShadowWrite() {
+ size_t size = aligned_end - aligned_start;
+ mprotect(tmp_start, size, PROT_READ);
+ void* res = mremap(tmp_start, size, size, MREMAP_MAYMOVE | MREMAP_FIXED,
+ reinterpret_cast<void*>(aligned_start));
+ CHECK(res != MAP_FAILED);
+ }
+};
+
+void CFIShadowWriter::FixupVmaName() {
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *shadow_start, kShadowSize, "cfi shadow");
+}
+
+void CFIShadowWriter::AddConstant(uintptr_t begin, uintptr_t end, uint16_t v) {
+ uint16_t* shadow_begin = MemToShadow(begin);
+ uint16_t* shadow_end = MemToShadow(end - 1) + 1;
+
+ ShadowWrite sw(shadow_begin, shadow_end);
+ std::fill(sw.begin(), sw.end(), v);
+}
+
+void CFIShadowWriter::AddUnchecked(uintptr_t begin, uintptr_t end) {
+ AddConstant(begin, end, kUncheckedShadow);
+}
+
+void CFIShadowWriter::AddInvalid(uintptr_t begin, uintptr_t end) {
+ AddConstant(begin, end, kInvalidShadow);
+}
+
+void CFIShadowWriter::Add(uintptr_t begin, uintptr_t end, uintptr_t cfi_check) {
+ CHECK((cfi_check & (kCfiCheckAlign - 1)) == 0);
+
+ // Don't fill anything below cfi_check. We can not represent those addresses
+ // in the shadow, and must make sure at codegen to place all valid call
+ // targets above cfi_check.
+ begin = std::max(begin, cfi_check) & ~(kShadowAlign - 1);
+ uint16_t* shadow_begin = MemToShadow(begin);
+ uint16_t* shadow_end = MemToShadow(end - 1) + 1;
+
+ ShadowWrite sw(shadow_begin, shadow_end);
+ uint16_t sv_begin = ((begin + kShadowAlign - cfi_check) >> kCfiCheckGranularity) + kRegularShadowMin;
+
+ // With each step of the loop below, __cfi_check address computation base is increased by
+ // 2**ShadowGranularity.
+ // To compensate for that, each next shadow value must be increased by 2**ShadowGranularity /
+ // 2**CfiCheckGranularity.
+ uint16_t sv_step = 1 << (kShadowGranularity - kCfiCheckGranularity);
+ uint16_t sv = sv_begin;
+ for (uint16_t& s : sw) {
+ if (sv < sv_begin) {
+ // If shadow value wraps around, also fall back to unchecked. This means the binary is too
+ // large. FIXME: consider using a (slow) resolution function instead.
+ s = kUncheckedShadow;
+ continue;
+ }
+ // If there is something there already, fall back to unchecked. This may happen in rare cases
+ // with MAP_FIXED libraries. FIXME: consider using a (slow) resolution function instead.
+ s = (s == kInvalidShadow) ? sv : kUncheckedShadow;
+ sv += sv_step;
+ }
+}
+
+static soinfo* find_libdl(soinfo* solist) {
+ for (soinfo* si = solist; si != nullptr; si = si->next) {
+ const char* soname = si->get_soname();
+ if (soname && strcmp(soname, "libdl.so") == 0) {
+ return si;
+ }
+ }
+ return nullptr;
+}
+
+static uintptr_t soinfo_find_symbol(soinfo* si, const char* s) {
+ SymbolName name(s);
+ const ElfW(Sym) * sym;
+ if (si->find_symbol_by_name(name, nullptr, &sym) && sym) {
+ return si->resolve_symbol_address(sym);
+ }
+ return 0;
+}
+
+uintptr_t soinfo_find_cfi_check(soinfo* si) {
+ return soinfo_find_symbol(si, "__cfi_check");
+}
+
+uintptr_t CFIShadowWriter::MapShadow() {
+ void* p =
+ mmap(nullptr, kShadowSize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ CHECK(p != MAP_FAILED);
+ return reinterpret_cast<uintptr_t>(p);
+}
+
+bool CFIShadowWriter::AddLibrary(soinfo* si) {
+ CHECK(shadow_start != nullptr);
+ if (si->base == 0 || si->size == 0) {
+ return true;
+ }
+ uintptr_t cfi_check = soinfo_find_cfi_check(si);
+ if (cfi_check == 0) {
+ INFO("[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
+ static_cast<uintptr_t>(si->size), si->get_soname());
+ AddUnchecked(si->base, si->base + si->size);
+ return true;
+ }
+
+ INFO("[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
+ static_cast<uintptr_t>(si->size), si->get_soname(), cfi_check);
+#ifdef __arm__
+ // Require Thumb encoding.
+ if ((cfi_check & 1UL) != 1UL) {
+ DL_ERR("__cfi_check in not a Thumb function in the library \"%s\"", si->get_soname());
+ return false;
+ }
+ cfi_check &= ~1UL;
+#endif
+ if ((cfi_check & (kCfiCheckAlign - 1)) != 0) {
+ DL_ERR("unaligned __cfi_check in the library \"%s\"", si->get_soname());
+ return false;
+ }
+ Add(si->base, si->base + si->size, cfi_check);
+ return true;
+}
+
+// Pass the shadow mapping address to libdl.so. In return, we get an pointer to the location
+// libdl.so uses to store the address.
+bool CFIShadowWriter::NotifyLibDl(soinfo* solist, uintptr_t p) {
+ soinfo* libdl = find_libdl(solist);
+ if (libdl == nullptr) {
+ DL_ERR("CFI could not find libdl");
+ return false;
+ }
+
+ uintptr_t cfi_init = soinfo_find_symbol(libdl, "__cfi_init");
+ CHECK(cfi_init != 0);
+ shadow_start = reinterpret_cast<uintptr_t* (*)(uintptr_t)>(cfi_init)(p);
+ CHECK(shadow_start != nullptr);
+ CHECK(*shadow_start == p);
+ mprotect(shadow_start, PAGE_SIZE, PROT_READ);
+ return true;
+}
+
+bool CFIShadowWriter::MaybeInit(soinfo* new_si, soinfo* solist) {
+ CHECK(initial_link_done);
+ CHECK(shadow_start == nullptr);
+ // Check if CFI shadow must be initialized at this time.
+ bool found = false;
+ if (new_si == nullptr) {
+ // This is the case when we've just completed the initial link. There may have been earlier
+ // calls to MaybeInit that were skipped. Look though the entire solist.
+ for (soinfo* si = solist; si != nullptr; si = si->next) {
+ if (soinfo_find_cfi_check(si)) {
+ found = true;
+ break;
+ }
+ }
+ } else {
+ // See if the new library uses CFI.
+ found = soinfo_find_cfi_check(new_si);
+ }
+
+ // Nothing found.
+ if (!found) {
+ return true;
+ }
+
+ // Init shadow and add all currently loaded libraries (not just the new ones).
+ if (!NotifyLibDl(solist, MapShadow()))
+ return false;
+ for (soinfo* si = solist; si != nullptr; si = si->next) {
+ if (!AddLibrary(si))
+ return false;
+ }
+ FixupVmaName();
+ return true;
+}
+
+bool CFIShadowWriter::AfterLoad(soinfo* si, soinfo* solist) {
+ if (!initial_link_done) {
+ // Too early.
+ return true;
+ }
+
+ if (shadow_start == nullptr) {
+ return MaybeInit(si, solist);
+ }
+
+ // Add the new library to the CFI shadow.
+ if (!AddLibrary(si))
+ return false;
+ FixupVmaName();
+ return true;
+}
+
+void CFIShadowWriter::BeforeUnload(soinfo* si) {
+ if (shadow_start == nullptr) return;
+ if (si->base == 0 || si->size == 0) return;
+ INFO("[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
+ static_cast<uintptr_t>(si->size), si->get_soname());
+ AddInvalid(si->base, si->base + si->size);
+ FixupVmaName();
+}
+
+bool CFIShadowWriter::InitialLinkDone(soinfo* solist) {
+ CHECK(!initial_link_done);
+ initial_link_done = true;
+ return MaybeInit(nullptr, solist);
+}
+
+// Find __cfi_check in the caller and let it handle the problem. Since caller_pc is likely not a
+// valid CFI target, we can not use CFI shadow for lookup. This does not need to be fast, do the
+// regular symbol lookup.
+void CFIShadowWriter::CfiFail(uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void* CallerPc) {
+ soinfo* si = find_containing_library(CallerPc);
+ if (!si) {
+ __builtin_trap();
+ }
+
+ uintptr_t cfi_check = soinfo_find_cfi_check(si);
+ if (!cfi_check) {
+ __builtin_trap();
+ }
+
+ reinterpret_cast<CFICheckFn>(cfi_check)(CallSiteTypeId, Ptr, DiagData);
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_cfi.h
^
|
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "hybris_compat.h"
+
+#include "linker.h"
+#include "linker_debug.h"
+
+#include <algorithm>
+
+#include "private/CFIShadow.h"
+
+// This class keeps the contents of CFI shadow up-to-date with the current set of loaded libraries.
+// See the comment in CFIShadow.h for more context.
+// See documentation in http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#shared-library-support.
+//
+// Shadow is mapped and initialized lazily as soon as the first CFI-enabled DSO is loaded.
+// It is updated after any library is loaded (but before any constructors are ran), and
+// before any library is unloaded.
+class CFIShadowWriter : private CFIShadow {
+ // Returns pointer to the shadow element for an address.
+ uint16_t* MemToShadow(uintptr_t x) {
+ return reinterpret_cast<uint16_t*>(*shadow_start + MemToShadowOffset(x));
+ }
+
+ // Update shadow for the address range to the given constant value.
+ void AddConstant(uintptr_t begin, uintptr_t end, uint16_t v);
+
+ // Update shadow for the address range to kUncheckedShadow.
+ void AddUnchecked(uintptr_t begin, uintptr_t end);
+
+ // Update shadow for the address range to kInvalidShadow.
+ void AddInvalid(uintptr_t begin, uintptr_t end);
+
+ // Update shadow for the address range to the given __cfi_check value.
+ void Add(uintptr_t begin, uintptr_t end, uintptr_t cfi_check);
+
+ // Add a DSO to CFI shadow.
+ bool AddLibrary(soinfo* si);
+
+ // Map CFI shadow.
+ uintptr_t MapShadow();
+
+ // Initialize CFI shadow and update its contents for everything in solist if any loaded library is
+ // CFI-enabled. If new_si != nullptr, do an incremental check by looking only at new_si; otherwise
+ // look at the entire solist.
+ bool MaybeInit(soinfo *new_si, soinfo *solist);
+
+ // Set a human readable name for the entire shadow region.
+ void FixupVmaName();
+
+ // Pass the pointer to the mapped shadow region to libdl. Must only be called once.
+ // Flips shadow_start to a non-nullptr value.
+ bool NotifyLibDl(soinfo *solist, uintptr_t p);
+
+ // Pointer to the shadow start address.
+ uintptr_t *shadow_start;
+
+ bool initial_link_done;
+
+ public:
+ // Update shadow after loading a DSO.
+ // This function will initialize the shadow if it sees a CFI-enabled DSO for the first time.
+ // In that case it will retroactively update shadow for all previously loaded DSOs. "solist" is a
+ // pointer to the global list.
+ // This function must be called before any user code has observed the newly loaded DSO.
+ bool AfterLoad(soinfo* si, soinfo *solist);
+
+ // Update shadow before unloading a DSO.
+ void BeforeUnload(soinfo* si);
+
+ // This is called as soon as the initial set of libraries is linked.
+ bool InitialLinkDone(soinfo *solist);
+
+ // Handle failure to locate __cfi_check for a target address.
+ static void CfiFail(uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void *caller_pc);
+};
+
+CFIShadowWriter* get_cfi_shadow();
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_common_types.h
^
|
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <android/dlext.h>
+#include "linked_list.h"
+
+#include <android-base/macros.h>
+
+// TODO(dimitry): move this to linker_defines.h? Unless it is removed by
+// consequent refactoring steps.
+
+// Android uses RELA for aarch64 and x86_64. mips64 still uses REL.
+#if defined(__aarch64__) || defined(__x86_64__)
+#define USE_RELA 1
+#endif
+
+
+struct soinfo;
+
+class SoinfoListAllocator {
+ public:
+ static LinkedListEntry<soinfo>* alloc();
+ static void free(LinkedListEntry<soinfo>* entry);
+
+ private:
+ // unconstructable
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SoinfoListAllocator);
+};
+
+class NamespaceListAllocator {
+ public:
+ static LinkedListEntry<android_namespace_t>* alloc();
+ static void free(LinkedListEntry<android_namespace_t>* entry);
+
+ private:
+ // unconstructable
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceListAllocator);
+};
+
+typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
+typedef LinkedList<android_namespace_t, NamespaceListAllocator> android_namespace_list_t;
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_config.cpp
^
|
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_config.h"
+
+#include "linker_globals.h"
+#include "linker_debug.h"
+#include "linker_utils.h"
+
+//#include <android-base/file.h>
+#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
+//#include <android-base/strings.h>
+
+#include <async_safe/log.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <string>
+#include <unordered_map>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+class ConfigParser {
+ public:
+ enum {
+ kPropertyAssign,
+ kPropertyAppend,
+ kSection,
+ kEndOfFile,
+ kError,
+ };
+
+ explicit ConfigParser(std::string&& content)
+ : content_(std::move(content)), p_(0), lineno_(0), was_end_of_file_(false) {}
+
+ /*
+ * Possible return values
+ * kPropertyAssign: name is set to property name and value is set to property value
+ * kPropertyAppend: same as kPropertyAssign, but the value should be appended
+ * kSection: name is set to section name.
+ * kEndOfFile: reached end of file.
+ * kError: error_msg is set.
+ */
+ int next_token(std::string* name, std::string* value, std::string* error_msg) {
+ std::string line;
+ while(NextLine(&line)) {
+ size_t found = line.find('#');
+ line = trim(line.substr(0, found));
+
+ if (line.empty()) {
+ continue;
+ }
+
+ if (line[0] == '[' && line.back() == ']') {
+ *name = line.substr(1, line.size() - 2);
+ return kSection;
+ }
+
+ size_t found_assign = line.find('=');
+ size_t found_append = line.find("+=");
+ if (found_assign != std::string::npos && found_append == std::string::npos) {
+ *name = trim(line.substr(0, found_assign));
+ *value = trim(line.substr(found_assign + 1));
+ return kPropertyAssign;
+ }
+
+ if (found_append != std::string::npos) {
+ *name = trim(line.substr(0, found_append));
+ *value = trim(line.substr(found_append + 2));
+ return kPropertyAppend;
+ }
+
+ *error_msg = std::string("invalid format: ") +
+ line +
+ ", expected \"name = property\", \"name += property\", or \"[section]\"";
+ return kError;
+ }
+
+ // to avoid infinite cycles when programmer makes a mistake
+ CHECK(!was_end_of_file_);
+ was_end_of_file_ = true;
+ return kEndOfFile;
+ }
+
+ size_t lineno() const {
+ return lineno_;
+ }
+
+ private:
+ bool NextLine(std::string* line) {
+ if (p_ == std::string::npos) {
+ return false;
+ }
+
+ size_t found = content_.find('\n', p_);
+ if (found != std::string::npos) {
+ *line = content_.substr(p_, found - p_);
+ p_ = found + 1;
+ } else {
+ *line = content_.substr(p_);
+ p_ = std::string::npos;
+ }
+
+ lineno_++;
+ return true;
+ }
+
+ std::string content_;
+ size_t p_;
+ size_t lineno_;
+ bool was_end_of_file_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ConfigParser);
+};
+
+class PropertyValue {
+ public:
+ PropertyValue() = default;
+
+ PropertyValue(std::string&& value, size_t lineno)
+ : value_(std::move(value)), lineno_(lineno) {}
+
+ const std::string& value() const {
+ return value_;
+ }
+
+ void append_value(std::string&& value) {
+ value_ = value_ + value;
+ // lineno isn't updated as we might have cases like this:
+ // property.x = blah
+ // property.y = blah
+ // property.x += blah
+ }
+
+ size_t lineno() const {
+ return lineno_;
+ }
+
+ private:
+ std::string value_;
+ size_t lineno_;
+};
+
+static std::string create_error_msg(const char* file,
+ size_t lineno,
+ const std::string& msg) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s:%zu: error: %s", file, lineno, msg.c_str());
+
+ return std::string(buf);
+}
+
+static bool parse_config_file(const char* ld_config_file_path,
+ const char* binary_realpath,
+ std::unordered_map<std::string, PropertyValue>* properties,
+ std::string* error_msg) {
+ std::string content;
+ if (!readFileToString(ld_config_file_path, &content)) {
+ if (errno != ENOENT) {
+ *error_msg = std::string("error reading file \"") +
+ ld_config_file_path + "\": " + strerror(errno);
+ }
+ return false;
+ }
+
+ ConfigParser cp(std::move(content));
+
+ std::string section_name;
+
+ while (true) {
+ std::string name;
+ std::string value;
+ std::string error;
+
+ int result = cp.next_token(&name, &value, &error);
+ if (result == ConfigParser::kError) {
+ DL_WARN("%s:%zd: warning: couldn't parse %s (ignoring this line)",
+ ld_config_file_path,
+ cp.lineno(),
+ error.c_str());
+ continue;
+ }
+
+ if (result == ConfigParser::kSection || result == ConfigParser::kEndOfFile) {
+ return false;
+ }
+
+ if (result == ConfigParser::kPropertyAssign) {
+ if (!startsWith(name, "dir.")) {
+ DL_WARN("%s:%zd: warning: unexpected property name \"%s\", "
+ "expected format dir.<section_name> (ignoring this line)",
+ ld_config_file_path,
+ cp.lineno(),
+ name.c_str());
+ continue;
+ }
+
+ // remove trailing '/'
+ while (!value.empty() && value.back() == '/') {
+ value.pop_back();
+ }
+
+ if (value.empty()) {
+ DL_WARN("%s:%zd: warning: property value is empty (ignoring this line)",
+ ld_config_file_path,
+ cp.lineno());
+ continue;
+ }
+
+ // If the path can be resolved, resolve it
+ char buf[PATH_MAX];
+ std::string resolved_path;
+ if (access(value.c_str(), R_OK) != 0) {
+ if (errno == ENOENT) {
+ // no need to test for non-existing path. skip.
+ continue;
+ }
+ // If not accessible, don't call realpath as it will just cause
+ // SELinux denial spam. Use the path unresolved.
+ resolved_path = value;
+ } else if (realpath(value.c_str(), buf)) {
+ resolved_path = buf;
+ } else {
+ // realpath is expected to fail with EPERM in some situations, so log
+ // the failure with INFO rather than DL_WARN. e.g. A binary in
+ // /data/local/tmp may attempt to stat /postinstall. See
+ // http://b/120996057.
+ INFO("%s:%zd: warning: path \"%s\" couldn't be resolved: %s",
+ ld_config_file_path,
+ cp.lineno(),
+ value.c_str(),
+ strerror(errno));
+ resolved_path = value;
+ }
+
+ if (file_is_under_dir(binary_realpath, resolved_path)) {
+ section_name = name.substr(4);
+ break;
+ }
+ }
+ }
+
+ INFO("[ Using config section \"%s\" ]", section_name.c_str());
+
+ // skip everything until we meet a correct section
+ while (true) {
+ std::string name;
+ std::string value;
+ std::string error;
+
+ int result = cp.next_token(&name, &value, &error);
+
+ if (result == ConfigParser::kSection && name == section_name) {
+ break;
+ }
+
+ if (result == ConfigParser::kEndOfFile) {
+ *error_msg = create_error_msg(ld_config_file_path,
+ cp.lineno(),
+ std::string("section \"") + section_name + "\" not found");
+ return false;
+ }
+ }
+
+ // found the section - parse it
+ while (true) {
+ std::string name;
+ std::string value;
+ std::string error;
+
+ int result = cp.next_token(&name, &value, &error);
+
+ if (result == ConfigParser::kEndOfFile || result == ConfigParser::kSection) {
+ break;
+ }
+
+ if (result == ConfigParser::kPropertyAssign) {
+ if (properties->find(name) != properties->end()) {
+ DL_WARN("%s:%zd: warning: redefining property \"%s\" (overriding previous value)",
+ ld_config_file_path,
+ cp.lineno(),
+ name.c_str());
+ }
+
+ (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
+ } else if (result == ConfigParser::kPropertyAppend) {
+ if (properties->find(name) == properties->end()) {
+ DL_WARN("%s:%zd: warning: appending to undefined property \"%s\" (treating as assignment)",
+ ld_config_file_path,
+ cp.lineno(),
+ name.c_str());
+ (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
+ } else {
+ if (endsWith(name, ".links") ||
+ endsWith(name, ".namespaces")) {
+ value = "," + value;
+ (*properties)[name].append_value(std::move(value));
+ } else if (endsWith(name, ".paths") ||
+ endsWith(name, ".shared_libs")) {
+ value = ":" + value;
+ (*properties)[name].append_value(std::move(value));
+ } else {
+ DL_WARN("%s:%zd: warning: += isn't allowed for property \"%s\" (ignoring)",
+ ld_config_file_path,
+ cp.lineno(),
+ name.c_str());
+ }
+ }
+ }
+
+ if (result == ConfigParser::kError) {
+ DL_WARN("%s:%zd: warning: couldn't parse %s (ignoring this line)",
+ ld_config_file_path,
+ cp.lineno(),
+ error.c_str());
+ continue;
+ }
+ }
+
+ return true;
+}
+
+static Config g_config;
+
+static constexpr const char* kDefaultConfigName = "default";
+static constexpr const char* kPropertyAdditionalNamespaces = "additional.namespaces";
+#if defined(__LP64__)
+static constexpr const char* kLibParamValue = "lib64";
+#else
+static constexpr const char* kLibParamValue = "lib";
+#endif
+
+class Properties {
+ public:
+ explicit Properties(std::unordered_map<std::string, PropertyValue>&& properties)
+ : properties_(std::move(properties)), target_sdk_version_(__ANDROID_API__) {}
+
+ std::vector<std::string> get_strings(const std::string& name, size_t* lineno = nullptr) const {
+ auto it = find_property(name, lineno);
+ if (it == properties_.end()) {
+ // return empty vector
+ return std::vector<std::string>();
+ }
+
+ std::vector<std::string> strings = split(it->second.value(), ",");
+
+ for (size_t i = 0; i < strings.size(); ++i) {
+ strings[i] = trim(strings[i]);
+ }
+
+ return strings;
+ }
+
+ bool get_bool(const std::string& name, size_t* lineno = nullptr) const {
+ auto it = find_property(name, lineno);
+ if (it == properties_.end()) {
+ return false;
+ }
+
+ return it->second.value() == "true";
+ }
+
+ std::string get_string(const std::string& name, size_t* lineno = nullptr) const {
+ auto it = find_property(name, lineno);
+ return (it == properties_.end()) ? "" : it->second.value();
+ }
+
+ std::vector<std::string> get_paths(const std::string& name, bool resolve, size_t* lineno = nullptr) {
+ std::string paths_str = get_string(name, lineno);
+
+ std::vector<std::string> paths;
+ split_path(paths_str.c_str(), ":", &paths);
+
+ std::vector<std::pair<std::string, std::string>> params;
+ params.push_back({ "LIB", kLibParamValue });
+ if (target_sdk_version_ != 0) {
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%d", target_sdk_version_);
+ params.push_back({ "SDK_VER", buf });
+ }
+
+ static std::string vndk = Config::get_vndk_version_string('-');
+ params.push_back({ "VNDK_VER", vndk });
+
+ for (auto& path : paths) {
+ format_string(&path, params);
+ }
+
+ if (resolve) {
+ std::vector<std::string> resolved_paths;
+
+ // do not remove paths that do not exist
+ resolve_paths(paths, &resolved_paths);
+
+ return resolved_paths;
+ } else {
+ return paths;
+ }
+ }
+
+ void set_target_sdk_version(int target_sdk_version) {
+ target_sdk_version_ = target_sdk_version;
+ }
+
+ private:
+ std::unordered_map<std::string, PropertyValue>::const_iterator
+ find_property(const std::string& name, size_t* lineno) const {
+ auto it = properties_.find(name);
+ if (it != properties_.end() && lineno != nullptr) {
+ *lineno = it->second.lineno();
+ }
+
+ return it;
+ }
+ std::unordered_map<std::string, PropertyValue> properties_;
+ int target_sdk_version_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Properties);
+};
+
+bool Config::read_binary_config(const char* ld_config_file_path,
+ const char* binary_realpath,
+ bool is_asan,
+ const Config** config,
+ std::string* error_msg) {
+ g_config.clear();
+
+ std::unordered_map<std::string, PropertyValue> property_map;
+ if (!parse_config_file(ld_config_file_path, binary_realpath, &property_map, error_msg)) {
+ return false;
+ }
+
+ Properties properties(std::move(property_map));
+
+ auto failure_guard = android::base::make_scope_guard([] { g_config.clear(); });
+
+ std::unordered_map<std::string, NamespaceConfig*> namespace_configs;
+
+ namespace_configs[kDefaultConfigName] = g_config.create_namespace_config(kDefaultConfigName);
+
+ std::vector<std::string> additional_namespaces = properties.get_strings(kPropertyAdditionalNamespaces);
+ for (const auto& name : additional_namespaces) {
+ namespace_configs[name] = g_config.create_namespace_config(name);
+ }
+
+ bool versioning_enabled = properties.get_bool("enable.target.sdk.version");
+ int target_sdk_version = __ANDROID_API__;
+ if (versioning_enabled) {
+ std::string version_file = dirname(binary_realpath) + "/.version";
+ std::string content;
+ if (!readFileToString(version_file, &content)) {
+ if (errno != ENOENT) {
+ *error_msg = std::string("error reading version file \"") +
+ version_file + "\": " + strerror(errno);
+ return false;
+ }
+ } else {
+ content = trim(content);
+ errno = 0;
+ char* end = nullptr;
+ const char* content_str = content.c_str();
+ int result = strtol(content_str, &end, 10);
+ if (errno == 0 && *end == '\0' && result > 0) {
+ target_sdk_version = result;
+ properties.set_target_sdk_version(target_sdk_version);
+ } else {
+ *error_msg = std::string("invalid version \"") + version_file + "\": \"" + content +"\"";
+ return false;
+ }
+ }
+ }
+
+ g_config.set_target_sdk_version(target_sdk_version);
+
+ for (const auto& ns_config_it : namespace_configs) {
+ auto& name = ns_config_it.first;
+ NamespaceConfig* ns_config = ns_config_it.second;
+
+ std::string property_name_prefix = std::string("namespace.") + name;
+
+ size_t lineno = 0;
+ std::vector<std::string> linked_namespaces =
+ properties.get_strings(property_name_prefix + ".links", &lineno);
+
+ for (const auto& linked_ns_name : linked_namespaces) {
+ if (namespace_configs.find(linked_ns_name) == namespace_configs.end()) {
+ *error_msg = create_error_msg(ld_config_file_path,
+ lineno,
+ std::string("undefined namespace: ") + linked_ns_name);
+ return false;
+ }
+
+ bool allow_all_shared_libs = properties.get_bool(property_name_prefix + ".link." +
+ linked_ns_name + ".allow_all_shared_libs");
+
+ std::string shared_libs = properties.get_string(property_name_prefix +
+ ".link." +
+ linked_ns_name +
+ ".shared_libs", &lineno);
+
+ if (!allow_all_shared_libs && shared_libs.empty()) {
+ *error_msg = create_error_msg(ld_config_file_path,
+ lineno,
+ std::string("list of shared_libs for ") +
+ name +
+ "->" +
+ linked_ns_name +
+ " link is not specified or is empty.");
+ return false;
+ }
+
+ if (allow_all_shared_libs && !shared_libs.empty()) {
+ *error_msg = create_error_msg(ld_config_file_path, lineno,
+ std::string("both shared_libs and allow_all_shared_libs "
+ "are set for ") +
+ name + "->" + linked_ns_name + " link.");
+ return false;
+ }
+
+ ns_config->add_namespace_link(linked_ns_name, shared_libs, allow_all_shared_libs);
+ }
+
+ ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));
+ ns_config->set_visible(properties.get_bool(property_name_prefix + ".visible"));
+
+ std::string whitelisted =
+ properties.get_string(property_name_prefix + ".whitelisted", &lineno);
+ if (!whitelisted.empty()) {
+ ns_config->set_whitelisted_libs(split(whitelisted, ":"));
+ }
+
+ // these are affected by is_asan flag
+ if (is_asan) {
+ property_name_prefix += ".asan";
+ }
+
+ // search paths are resolved (canonicalized). This is required mainly for
+ // the case when /vendor is a symlink to /system/vendor, which is true for
+ // non Treble-ized legacy devices.
+ ns_config->set_search_paths(properties.get_paths(property_name_prefix + ".search.paths", true));
+
+ // However, for permitted paths, we are not required to resolve the paths
+ // since they are only set for isolated namespaces, which implies the device
+ // is Treble-ized (= /vendor is not a symlink to /system/vendor).
+ // In fact, the resolving is causing an unexpected side effect of selinux
+ // denials on some executables which are not allowed to access some of the
+ // permitted paths.
+ ns_config->set_permitted_paths(properties.get_paths(property_name_prefix + ".permitted.paths", false));
+ }
+
+ failure_guard.Disable();
+ *config = &g_config;
+ return true;
+}
+
+std::string Config::get_vndk_version_string(const char delimiter) {
+ /*std::string version = android::base::GetProperty("ro.vndk.version", "");
+ if (version != "" && version != "current") {
+ //add the delimiter char in front of the string and return it.
+ return version.insert(0, 1, delimiter);
+ }*/
+ return "";
+}
+
+NamespaceConfig* Config::create_namespace_config(const std::string& name) {
+ namespace_configs_.push_back(std::unique_ptr<NamespaceConfig>(new NamespaceConfig(name)));
+ NamespaceConfig* ns_config_ptr = namespace_configs_.back().get();
+ namespace_configs_map_[name] = ns_config_ptr;
+ return ns_config_ptr;
+}
+
+void Config::clear() {
+ namespace_configs_.clear();
+ namespace_configs_map_.clear();
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_config.h
^
|
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <android/api-level.h>
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#include <android-base/macros.h>
+
+class NamespaceLinkConfig {
+ public:
+ NamespaceLinkConfig() = default;
+ NamespaceLinkConfig(const std::string& ns_name, const std::string& shared_libs,
+ bool allow_all_shared_libs)
+ : ns_name_(ns_name), shared_libs_(shared_libs),
+ allow_all_shared_libs_(allow_all_shared_libs) {}
+
+ const std::string& ns_name() const {
+ return ns_name_;
+ }
+
+ const std::string& shared_libs() const {
+ return shared_libs_;
+ }
+
+ bool allow_all_shared_libs() const {
+ return allow_all_shared_libs_;
+ }
+
+ private:
+ std::string ns_name_;
+ std::string shared_libs_;
+ bool allow_all_shared_libs_;
+};
+
+class NamespaceConfig {
+ public:
+ explicit NamespaceConfig(const std::string& name)
+ : name_(name), isolated_(false), visible_(false)
+ {}
+
+ const char* name() const {
+ return name_.c_str();
+ }
+
+ bool isolated() const {
+ return isolated_;
+ }
+
+ bool visible() const {
+ return visible_;
+ }
+
+ const std::vector<std::string>& search_paths() const {
+ return search_paths_;
+ }
+
+ const std::vector<std::string>& permitted_paths() const {
+ return permitted_paths_;
+ }
+
+ const std::vector<std::string>& whitelisted_libs() const {
+ return whitelisted_libs_;
+ }
+
+ const std::vector<NamespaceLinkConfig>& links() const {
+ return namespace_links_;
+ }
+
+ void add_namespace_link(const std::string& ns_name, const std::string& shared_libs,
+ bool allow_all_shared_libs) {
+ namespace_links_.push_back(NamespaceLinkConfig(ns_name, shared_libs, allow_all_shared_libs));
+ }
+
+ void set_isolated(bool isolated) {
+ isolated_ = isolated;
+ }
+
+ void set_visible(bool visible) {
+ visible_ = visible;
+ }
+
+ void set_search_paths(std::vector<std::string>&& search_paths) {
+ search_paths_ = std::move(search_paths);
+ }
+
+ void set_permitted_paths(std::vector<std::string>&& permitted_paths) {
+ permitted_paths_ = std::move(permitted_paths);
+ }
+
+ void set_whitelisted_libs(std::vector<std::string>&& whitelisted_libs) {
+ whitelisted_libs_ = std::move(whitelisted_libs);
+ }
+ private:
+ const std::string name_;
+ bool isolated_;
+ bool visible_;
+ std::vector<std::string> search_paths_;
+ std::vector<std::string> permitted_paths_;
+ std::vector<std::string> whitelisted_libs_;
+ std::vector<NamespaceLinkConfig> namespace_links_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceConfig);
+};
+
+class Config {
+ public:
+ Config() : target_sdk_version_(__ANDROID_API__) {}
+
+ const std::vector<std::unique_ptr<NamespaceConfig>>& namespace_configs() const {
+ return namespace_configs_;
+ }
+
+ const NamespaceConfig* default_namespace_config() const {
+ auto it = namespace_configs_map_.find("default");
+ return it == namespace_configs_map_.end() ? nullptr : it->second;
+ }
+
+ int target_sdk_version() const {
+ return target_sdk_version_;
+ }
+
+ // note that this is one time event and therefore there is no need to
+ // read every section of the config. Every linker instance needs at
+ // most one configuration.
+ // Returns false in case of an error. If binary config was not found
+ // sets *config = nullptr.
+ static bool read_binary_config(const char* ld_config_file_path,
+ const char* binary_realpath,
+ bool is_asan,
+ const Config** config,
+ std::string* error_msg);
+
+ static std::string get_vndk_version_string(const char delimiter);
+ private:
+ void clear();
+
+ void set_target_sdk_version(int target_sdk_version) {
+ target_sdk_version_ = target_sdk_version;
+ }
+
+ NamespaceConfig* create_namespace_config(const std::string& name);
+
+ std::vector<std::unique_ptr<NamespaceConfig>> namespace_configs_;
+ std::unordered_map<std::string, NamespaceConfig*> namespace_configs_map_;
+ int target_sdk_version_;
+
+ DISALLOW_COPY_AND_ASSIGN(Config);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_config_test.cpp
^
|
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <gtest/gtest.h>
+
+#include "linker_config.h"
+#include "linker_utils.h"
+
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/scopeguard.h>
+#include <android-base/stringprintf.h>
+
+#if defined(__LP64__)
+#define ARCH_SUFFIX "64"
+#else
+#define ARCH_SUFFIX ""
+#endif
+
+static const char* config_str =
+ "# comment \n"
+ "dir.test = /data/local/tmp\n"
+ "\n"
+ "[test]\n"
+ "\n"
+ "enable.target.sdk.version = true\n"
+ "additional.namespaces=system\n"
+ "additional.namespaces+=vndk\n"
+ "additional.namespaces+=vndk_in_system\n"
+ "namespace.default.isolated = true\n"
+ "namespace.default.search.paths = /vendor/${LIB}\n"
+ "namespace.default.permitted.paths = /vendor/${LIB}\n"
+ "namespace.default.asan.search.paths = /data\n"
+ "namespace.default.asan.search.paths += /vendor/${LIB}\n"
+ "namespace.default.asan.permitted.paths = /data:/vendor\n"
+ "namespace.default.links = system\n"
+ "namespace.default.links += vndk\n"
+ // irregular whitespaces are added intentionally for testing purpose
+ "namespace.default.link.system.shared_libs= libc.so\n"
+ "namespace.default.link.system.shared_libs += libm.so:libdl.so\n"
+ "namespace.default.link.system.shared_libs +=libstdc++.so\n"
+ "namespace.default.link.vndk.shared_libs = libcutils.so:libbase.so\n"
+ "namespace.system.isolated = true\n"
+ "namespace.system.visible = true\n"
+ "namespace.system.search.paths = /system/${LIB}\n"
+ "namespace.system.permitted.paths = /system/${LIB}\n"
+ "namespace.system.asan.search.paths = /data:/system/${LIB}\n"
+ "namespace.system.asan.permitted.paths = /data:/system\n"
+ "namespace.vndk.isolated = tr\n"
+ "namespace.vndk.isolated += ue\n" // should be ignored and return as 'false'.
+ "namespace.vndk.search.paths = /system/${LIB}/vndk\n"
+ "namespace.vndk.asan.search.paths = /data\n"
+ "namespace.vndk.asan.search.paths += /system/${LIB}/vndk\n"
+ "namespace.vndk.links = default\n"
+ "namespace.vndk.link.default.allow_all_shared_libs = true\n"
+ "namespace.vndk.link.vndk_in_system.allow_all_shared_libs = true\n"
+ "namespace.vndk_in_system.isolated = true\n"
+ "namespace.vndk_in_system.visible = true\n"
+ "namespace.vndk_in_system.search.paths = /system/${LIB}\n"
+ "namespace.vndk_in_system.permitted.paths = /system/${LIB}\n"
+ "namespace.vndk_in_system.whitelisted = libz.so:libyuv.so:libtinyxml2.so\n"
+ "\n";
+
+static bool write_version(const std::string& path, uint32_t version) {
+ std::string content = android::base::StringPrintf("%d", version);
+ return android::base::WriteStringToFile(content, path);
+}
+
+static std::vector<std::string> resolve_paths(std::vector<std::string> paths) {
+ std::vector<std::string> resolved_paths;
+ resolve_paths(paths, &resolved_paths);
+ return resolved_paths;
+}
+
+static void run_linker_config_smoke_test(bool is_asan) {
+ const std::vector<std::string> kExpectedDefaultSearchPath =
+ resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/vendor/lib" ARCH_SUFFIX }) :
+ std::vector<std::string>({ "/vendor/lib" ARCH_SUFFIX }));
+
+ const std::vector<std::string> kExpectedDefaultPermittedPath =
+ resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/vendor" }) :
+ std::vector<std::string>({ "/vendor/lib" ARCH_SUFFIX }));
+
+ const std::vector<std::string> kExpectedSystemSearchPath =
+ resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/system/lib" ARCH_SUFFIX }) :
+ std::vector<std::string>({ "/system/lib" ARCH_SUFFIX }));
+
+ const std::vector<std::string> kExpectedSystemPermittedPath =
+ resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/system" }) :
+ std::vector<std::string>({ "/system/lib" ARCH_SUFFIX }));
+
+ const std::vector<std::string> kExpectedVndkSearchPath =
+ resolve_paths(is_asan ? std::vector<std::string>({ "/data", "/system/lib" ARCH_SUFFIX "/vndk"}) :
+ std::vector<std::string>({ "/system/lib" ARCH_SUFFIX "/vndk"}));
+
+ TemporaryFile tmp_file;
+ close(tmp_file.fd);
+ tmp_file.fd = -1;
+
+ android::base::WriteStringToFile(config_str, tmp_file.path);
+
+ TemporaryDir tmp_dir;
+
+ std::string executable_path = std::string(tmp_dir.path) + "/some-binary";
+ std::string version_file = std::string(tmp_dir.path) + "/.version";
+
+ auto file_guard =
+ android::base::make_scope_guard([&version_file] { unlink(version_file.c_str()); });
+
+ ASSERT_TRUE(write_version(version_file, 113U)) << strerror(errno);
+
+ // read config
+ const Config* config = nullptr;
+ std::string error_msg;
+ ASSERT_TRUE(Config::read_binary_config(tmp_file.path,
+ executable_path.c_str(),
+ is_asan,
+ &config,
+ &error_msg)) << error_msg;
+ ASSERT_TRUE(config != nullptr);
+ ASSERT_TRUE(error_msg.empty());
+
+ ASSERT_EQ(113, config->target_sdk_version());
+
+ const NamespaceConfig* default_ns_config = config->default_namespace_config();
+ ASSERT_TRUE(default_ns_config != nullptr);
+
+ ASSERT_TRUE(default_ns_config->isolated());
+ ASSERT_FALSE(default_ns_config->visible());
+ ASSERT_EQ(kExpectedDefaultSearchPath, default_ns_config->search_paths());
+ ASSERT_EQ(kExpectedDefaultPermittedPath, default_ns_config->permitted_paths());
+
+ const auto& default_ns_links = default_ns_config->links();
+ ASSERT_EQ(2U, default_ns_links.size());
+
+ ASSERT_EQ("system", default_ns_links[0].ns_name());
+ ASSERT_EQ("libc.so:libm.so:libdl.so:libstdc++.so", default_ns_links[0].shared_libs());
+ ASSERT_FALSE(default_ns_links[0].allow_all_shared_libs());
+
+ ASSERT_EQ("vndk", default_ns_links[1].ns_name());
+ ASSERT_EQ("libcutils.so:libbase.so", default_ns_links[1].shared_libs());
+ ASSERT_FALSE(default_ns_links[1].allow_all_shared_libs());
+
+ auto& ns_configs = config->namespace_configs();
+ ASSERT_EQ(4U, ns_configs.size());
+
+ // find second namespace
+ const NamespaceConfig* ns_system = nullptr;
+ const NamespaceConfig* ns_vndk = nullptr;
+ const NamespaceConfig* ns_vndk_in_system = nullptr;
+ for (auto& ns : ns_configs) {
+ std::string ns_name = ns->name();
+ ASSERT_TRUE(ns_name == "system" || ns_name == "default" ||
+ ns_name == "vndk" || ns_name == "vndk_in_system")
+ << "unexpected ns name: " << ns->name();
+
+ if (ns_name == "system") {
+ ns_system = ns.get();
+ } else if (ns_name == "vndk") {
+ ns_vndk = ns.get();
+ } else if (ns_name == "vndk_in_system") {
+ ns_vndk_in_system = ns.get();
+ }
+ }
+
+ ASSERT_TRUE(ns_system != nullptr) << "system namespace was not found";
+
+ ASSERT_TRUE(ns_system->isolated());
+ ASSERT_TRUE(ns_system->visible());
+ ASSERT_EQ(kExpectedSystemSearchPath, ns_system->search_paths());
+ ASSERT_EQ(kExpectedSystemPermittedPath, ns_system->permitted_paths());
+
+ ASSERT_TRUE(ns_vndk != nullptr) << "vndk namespace was not found";
+
+ ASSERT_FALSE(ns_vndk->isolated()); // malformed bool property
+ ASSERT_FALSE(ns_vndk->visible()); // undefined bool property
+ ASSERT_EQ(kExpectedVndkSearchPath, ns_vndk->search_paths());
+
+ const auto& ns_vndk_links = ns_vndk->links();
+ ASSERT_EQ(1U, ns_vndk_links.size());
+ ASSERT_EQ("default", ns_vndk_links[0].ns_name());
+ ASSERT_TRUE(ns_vndk_links[0].allow_all_shared_libs());
+
+ ASSERT_TRUE(ns_vndk_in_system != nullptr) << "vndk_in_system namespace was not found";
+ ASSERT_EQ(
+ std::vector<std::string>({"libz.so", "libyuv.so", "libtinyxml2.so"}),
+ ns_vndk_in_system->whitelisted_libs());
+}
+
+TEST(linker_config, smoke) {
+ run_linker_config_smoke_test(false);
+}
+
+TEST(linker_config, asan_smoke) {
+ run_linker_config_smoke_test(true);
+}
+
+TEST(linker_config, ns_link_shared_libs_invalid_settings) {
+ // This unit test ensures an error is emitted when a namespace link in ld.config.txt specifies
+ // both shared_libs and allow_all_shared_libs.
+
+ static const char config_str[] =
+ "dir.test = /data/local/tmp\n"
+ "\n"
+ "[test]\n"
+ "additional.namespaces = system\n"
+ "namespace.default.links = system\n"
+ "namespace.default.link.system.shared_libs = libc.so:libm.so\n"
+ "namespace.default.link.system.allow_all_shared_libs = true\n"
+ "\n";
+
+ TemporaryFile tmp_file;
+ close(tmp_file.fd);
+ tmp_file.fd = -1;
+
+ android::base::WriteStringToFile(config_str, tmp_file.path);
+
+ TemporaryDir tmp_dir;
+
+ std::string executable_path = std::string(tmp_dir.path) + "/some-binary";
+
+ const Config* config = nullptr;
+ std::string error_msg;
+ ASSERT_FALSE(Config::read_binary_config(tmp_file.path,
+ executable_path.c_str(),
+ false,
+ &config,
+ &error_msg));
+ ASSERT_TRUE(config == nullptr);
+ ASSERT_EQ(std::string(tmp_file.path) + ":6: "
+ "error: both shared_libs and allow_all_shared_libs are set for default->system link.",
+ error_msg);
+}
+
+TEST(linker_config, dir_path_resolve) {
+ // This unit test ensures the linker resolves paths of dir.${section}
+ // properties to real path.
+
+ TemporaryDir tmp_dir;
+
+ std::string sub_dir = std::string(tmp_dir.path) + "/subdir";
+ mkdir(sub_dir.c_str(), 0755);
+
+ auto subdir_guard =
+ android::base::make_scope_guard([&sub_dir] { rmdir(sub_dir.c_str()); });
+
+ std::string symlink_path = std::string(tmp_dir.path) + "/symlink";
+ symlink(sub_dir.c_str(), symlink_path.c_str());
+
+ auto symlink_guard =
+ android::base::make_scope_guard([&symlink_path] { unlink(symlink_path.c_str()); });
+
+ std::string config_str =
+ "dir.test = " + symlink_path + "\n"
+ "\n"
+ "[test]\n";
+
+ TemporaryFile tmp_file;
+ close(tmp_file.fd);
+ tmp_file.fd = -1;
+
+ android::base::WriteStringToFile(config_str, tmp_file.path);
+
+ std::string executable_path = sub_dir + "/some-binary";
+
+ const Config* config = nullptr;
+ std::string error_msg;
+
+ ASSERT_TRUE(Config::read_binary_config(tmp_file.path,
+ executable_path.c_str(),
+ false,
+ &config,
+ &error_msg)) << error_msg;
+
+ ASSERT_TRUE(config != nullptr) << error_msg;
+ ASSERT_TRUE(error_msg.empty()) << error_msg;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_debug.h
^
|
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+// You can increase the verbosity of debug traces by defining the LD_DEBUG
+// environment variable to a numeric value from 0 to 2 (corresponding to
+// INFO, TRACE, and DEBUG calls in the source). This will only
+// affect new processes being launched.
+
+// By default, traces are sent to logcat, with the "linker" tag. You can
+// change this to go to stdout instead by setting the definition of
+// LINKER_DEBUG_TO_LOG to 0.
+#define LINKER_DEBUG_TO_LOG 1
+
+#define TRACE_DEBUG 1
+#define DO_TRACE_LOOKUP 1
+#define DO_TRACE_RELO 1
+#define DO_TRACE_IFUNC 1
+#define TIMING 0
+#define STATS 0
+#define COUNT_PAGES 0
+
+/*********************************************************************
+ * You shouldn't need to modify anything below unless you are adding
+ * more debugging information.
+ *
+ * To enable/disable specific debug options, change the defines above
+ *********************************************************************/
+
+#include <unistd.h>
+
+#include <async_safe/log.h>
+#include <async_safe/CHECK.h>
+#include <sys/cdefs-android.h>
+
+__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
+
+#if LINKER_DEBUG_TO_LOG
+#define _PRINTVF(v, x...) \
+ do { \
+ if (g_ld_debug_verbosity > (v)) { fprintf(stderr, x); fprintf(stderr, "\n"); } \
+ } while (0)
+#else /* !LINKER_DEBUG_TO_LOG */
+#define _PRINTVF(v, x...) \
+ do { \
+ if (g_ld_debug_verbosity > (v)) { fprintf(stderr, x); fprintf(stderr, "\n"); } \
+ } while (0)
+#endif /* !LINKER_DEBUG_TO_LOG */
+
+#define PRINT(x...) _PRINTVF(-1, x)
+#define INFO(x...) _PRINTVF(0, x)
+#define TRACE(x...) _PRINTVF(1, x)
+
+#if TRACE_DEBUG
+#define DEBUG(x...) _PRINTVF(2, "DEBUG: " x)
+#else /* !TRACE_DEBUG */
+#define DEBUG(x...) do {} while (0)
+#endif /* TRACE_DEBUG */
+
+#define TRACE_TYPE(t, x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0)
+
+#if COUNT_PAGES
+extern uint32_t bitmask[];
+#if defined(__LP64__)
+#define MARK(offset) \
+ do { \
+ if ((((offset) >> 12) >> 5) < 4096) \
+ bitmask[((offset) >> 12) >> 5] |= (1 << (((offset) >> 12) & 31)); \
+ } while (0)
+#else
+#define MARK(offset) \
+ do { \
+ bitmask[((offset) >> 12) >> 3] |= (1 << (((offset) >> 12) & 7)); \
+ } while (0)
+#endif
+#else
+#define MARK(x) do {} while (0)
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_dlwarning.cpp
^
|
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_dlwarning.h"
+
+#include <strings.h>
+
+#include <string>
+
+#include "hybris_compat.h"
+
+static std::string current_msg;
+
+void add_dlwarning(const char* sopath, const char* message, const char* value) {
+ if (!current_msg.empty()) {
+ current_msg += '\n';
+ }
+
+ current_msg = current_msg + basename(sopath) + ": " + message;
+
+ if (value != nullptr) {
+ current_msg = current_msg + " \"" + value + "\"";
+ }
+}
+
+// Resets the current one (like dlerror but instead of
+// being thread-local it is process-local).
+void get_dlwarning(void* obj, void (*f)(void*, const char*)) {
+ if (current_msg.empty()) {
+ f(obj, nullptr);
+ } else {
+ std::string msg = current_msg;
+ current_msg.clear();
+ f(obj, msg.c_str());
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_dlwarning.h
^
|
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+void add_dlwarning(const char* sopath, const char* message, const char* value = nullptr);
+
+// Resets the current one (like dlerror but instead of
+// being thread-local it is process-local). The user_data
+// is used to avoid forcing user into saving the message
+// to a global variable.
+void get_dlwarning(void* user_data, void (*f)(void*, const char*));
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_exidx_static.c
^
|
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <link.h>
+
+/* Find the .ARM.exidx section (which in the case of a static executable
+ * can be identified through its start and end symbols), and return its
+ * beginning and numbe of entries to the caller. Note that for static
+ * executables we do not need to use the value of the PC to find the
+ * EXIDX section.
+ */
+
+extern unsigned __exidx_end;
+extern unsigned __exidx_start;
+
+_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc __unused,
+ int* pcount)
+{
+ *pcount = (__exidx_end-__exidx_start)/8;
+ return __exidx_start;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_gdb_support.cpp
^
|
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_gdb_support.h"
+
+#include <pthread.h>
+
+#include "private/ScopedPthreadMutexLocker.h"
+
+// This function is an empty stub where GDB locates a breakpoint to get notified
+// about linker activity.
+extern "C"
+void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity();
+
+r_debug _r_debug =
+ {1, nullptr, reinterpret_cast<uintptr_t>(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0};
+
+static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+static link_map* r_debug_head = nullptr;
+
+int _linker_enable_gdb_support = 0;
+
+void insert_link_map_into_debug_map(link_map* map) {
+ if (!_linker_enable_gdb_support) return;
+
+ // Stick the new library at the end of the list.
+ // gdb tends to care more about libc than it does
+ // about leaf libraries, and ordering it this way
+ // reduces the back-and-forth over the wire.
+
+ if(r_debug_head == nullptr && _r_debug.r_map != nullptr) {
+ link_map *glibc_link_map = new link_map(*_r_debug.r_map);
+ r_debug_head = glibc_link_map;
+
+ while(glibc_link_map->l_next != nullptr) {
+ link_map *copy_next_link_map = new link_map(*glibc_link_map->l_next);
+ glibc_link_map->l_next = copy_next_link_map;
+ copy_next_link_map->l_prev = glibc_link_map;
+
+ glibc_link_map = copy_next_link_map;
+ }
+ }
+
+ if (r_debug_head != nullptr) {
+ r_debug_head->l_prev = map;
+ map->l_next = r_debug_head;
+ map->l_prev = nullptr;
+ } else {
+ _r_debug.r_map = map;
+ map->l_prev = nullptr;
+ map->l_next = nullptr;
+ }
+ _r_debug.r_map = r_debug_head = map;
+}
+
+void remove_link_map_from_debug_map(link_map* map) {
+ if (!_linker_enable_gdb_support) return;
+
+ if (r_debug_head == map) {
+ r_debug_head = map->l_next;
+ }
+
+ if (map->l_prev) {
+ map->l_prev->l_next = map->l_next;
+ }
+ if (map->l_next) {
+ map->l_next->l_prev = map->l_prev;
+ }
+}
+
+void notify_gdb_of_load(link_map* map) {
+ ScopedPthreadMutexLocker locker(&g__r_debug_mutex);
+
+ _r_debug.r_state = r_debug::RT_ADD;
+ rtld_db_dlactivity();
+
+ insert_link_map_into_debug_map(map);
+
+ _r_debug.r_state = r_debug::RT_CONSISTENT;
+ rtld_db_dlactivity();
+}
+
+void notify_gdb_of_unload(link_map* map) {
+ ScopedPthreadMutexLocker locker(&g__r_debug_mutex);
+
+ _r_debug.r_state = r_debug::RT_DELETE;
+ rtld_db_dlactivity();
+
+ remove_link_map_from_debug_map(map);
+
+ _r_debug.r_state = r_debug::RT_CONSISTENT;
+ rtld_db_dlactivity();
+}
+
+void notify_gdb_of_libraries() {
+ _r_debug.r_state = r_debug::RT_ADD;
+ rtld_db_dlactivity();
+ _r_debug.r_state = r_debug::RT_CONSISTENT;
+ rtld_db_dlactivity();
+}
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_gdb_support.h
^
|
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <link.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+extern int _linker_enable_gdb_support;
+
+void insert_link_map_into_debug_map(link_map* map);
+void remove_link_map_from_debug_map(link_map* map);
+void notify_gdb_of_load(link_map* map);
+void notify_gdb_of_unload(link_map* map);
+void notify_gdb_of_libraries();
+
+extern struct r_debug _r_debug;
+
+__END_DECLS
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_globals.cpp
^
|
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker.h"
+#include "linker_globals.h"
+#include "linker_namespaces.h"
+#include "linker_utils.h"
+#include <stdarg.h>
+//#include "android-base/stringprintf.h"
+
+int g_argc = 0;
+char** g_argv = nullptr;
+char** g_envp = nullptr;
+
+std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map;
+
+static char __linker_dl_err_buf[768];
+
+char* linker_get_error_buffer() {
+ return &__linker_dl_err_buf[0];
+}
+
+size_t linker_get_error_buffer_size() {
+ return sizeof(__linker_dl_err_buf);
+}
+
+void DL_WARN_documented_change(int api_level, const char* doc_link, const char* fmt, ...) {
+ std::string result{"Warning: "};
+
+ va_list ap;
+ va_start(ap, fmt);
+ stringAppendV(&result, fmt, ap);
+ va_end(ap);
+
+ stringAppendF(&result,
+ " and will not work when the app moves to API level %d or later "
+ "(https://android.googlesource.com/platform/bionic/+/master/%s) "
+ "(allowing for now because this app's target API level is still %d)",
+ api_level, doc_link, get_application_target_sdk_version());
+ DL_WARN("%s", result.c_str());
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_globals.h
^
|
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <link.h>
+#include <stddef.h>
+
+#include <string>
+#include <unordered_map>
+
+#include <async_safe/log.h>
+
+#include <hybris_compat.h>
+
+#define DL_ERR(fmt, x...) \
+ do { \
+ fprintf(stderr, fmt, ##x); \
+ fprintf(stderr, "\n"); \
+ } while (false)
+
+#define DL_ERR_NO_PRINT(fmt, x...) \
+ do { \
+ } while (false)
+
+#define DL_WARN(fmt, x...) \
+ do { \
+ fprintf(stderr, "WARNING: linker " fmt, ##x); \
+ fprintf(stderr, "\n"); \
+ } while (false)
+
+void DL_WARN_documented_change(int api_level, const char* doc_link, const char* fmt, ...);
+
+#define DL_ERR_AND_LOG(fmt, x...) \
+ do { \
+ DL_ERR(fmt, x); \
+ PRINT(fmt, x); \
+ } while (false)
+
+constexpr ElfW(Versym) kVersymNotNeeded = 0;
+constexpr ElfW(Versym) kVersymGlobal = 1;
+
+// These values are used to call constructors for .init_array && .preinit_array
+extern int g_argc;
+extern char** g_argv;
+extern char** g_envp;
+
+struct soinfo;
+struct android_namespace_t;
+
+extern android_namespace_t *g_default_namespace;
+
+extern std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map;
+
+// Error buffer "variable"
+char* linker_get_error_buffer();
+size_t linker_get_error_buffer_size();
+extern void* (*_get_hooked_symbol)(const char *sym, const char *requester);
+
+#ifdef WANT_ARM_TRACING
+extern void *(*_create_wrapper)(const char *symbol, void *function, int wrapper_type);
+#endif
+
+class DlErrorRestorer {
+ public:
+ DlErrorRestorer() {
+ saved_error_msg_ = linker_get_error_buffer();
+ }
+ ~DlErrorRestorer() {
+ strlcpy(linker_get_error_buffer(), saved_error_msg_.c_str(), linker_get_error_buffer_size());
+ }
+ private:
+ std::string saved_error_msg_;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_libc_support.c
^
|
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "../libc/arch-common/bionic/__dso_handle.h"
+#include "../libc/arch-common/bionic/pthread_atfork.h"
+
+int atexit(void (*function)(void) __attribute__((__unused__))) {
+ return -1;
+}
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_libcxx_support.cpp
^
|
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <async_safe/log.h>
+
+void* __find_icu_symbol(const char* symbol_name __attribute__((__unused__))) {
+ async_safe_fatal("__find_icu_symbol should not be called in the linker");
+}
+
+extern "C" int __cxa_type_match() {
+ async_safe_fatal("__cxa_type_match is not implemented in the linker");
+}
+
+int posix_memalign(void**, size_t, size_t) {
+ async_safe_fatal("posix_memalign is not implemented in the linker");
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_logger.cpp
^
|
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_logger.h"
+
+#include <string.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <string>
+#include <vector>
+
+#include <async_safe/log.h>
+
+//#include "android-base/strings.h"
+#include "linker_utils.h"
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+#include "private/CachedProperty.h"
+#endif
+
+#include "hybris_compat.h"
+
+LinkerLogger g_linker_logger;
+bool g_greylist_disabled = false;
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+static uint32_t ParseProperty(const std::string& value) {
+ if (value.empty()) {
+ return 0;
+ }
+
+ std::vector<std::string> options = split(value, ",");
+
+ uint32_t flags = 0;
+
+ for (const auto& o : options) {
+ if (o == "dlerror") {
+ flags |= kLogErrors;
+ } else if (o == "dlopen") {
+ flags |= kLogDlopen;
+ } else if (o == "dlsym") {
+ flags |= kLogDlsym;
+ } else {
+ async_safe_format_log(ANDROID_LOG_WARN, "linker", "Ignoring unknown debug.ld option \"%s\"",
+ o.c_str());
+ }
+ }
+
+ return flags;
+}
+#endif
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+static void GetAppSpecificProperty(char* buffer) {
+ // Get process basename.
+ const char* process_name_start = basename(g_argv[0]);
+
+ // Remove ':' and everything after it. This is the naming convention for
+ // services: https://developer.android.com/guide/components/services.html
+ const char* process_name_end = strchr(process_name_start, ':');
+
+ std::string process_name = (process_name_end != nullptr) ?
+ std::string(process_name_start, (process_name_end - process_name_start)) :
+ std::string(process_name_start);
+
+ std::string property_name = std::string("debug.ld.app.") + process_name;
+ __system_property_get(property_name.c_str(), buffer);
+}
+#endif
+
+void LinkerLogger::ResetState() {
+ // The most likely scenario app is not debuggable and
+ // is running on a user build, in which case logging is disabled.
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
+ return;
+ }
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ // This is a convenient place to check whether the greylist should be disabled for testing.
+ static CachedProperty greylist_disabled("debug.ld.greylist_disabled");
+ bool old_value = g_greylist_disabled;
+ g_greylist_disabled = (strcmp(greylist_disabled.Get(), "true") == 0);
+ if (g_greylist_disabled != old_value) {
+ async_safe_format_log(ANDROID_LOG_INFO, "linker", "%s greylist",
+ g_greylist_disabled ? "Disabling" : "Enabling");
+ }
+
+ flags_ = 0;
+
+ // For logging, check the flag applied to all processes first.
+ static CachedProperty debug_ld_all("debug.ld.all");
+ flags_ |= ParseProperty(debug_ld_all.Get());
+#endif
+
+ // Safeguard against a NULL g_argv. Ignore processes started without argv (http://b/33276926).
+ if (g_argv == nullptr || g_argv[0] == nullptr) {
+ return;
+ }
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ // Otherwise check the app-specific property too.
+ // We can't easily cache the property here because argv[0] changes.
+ char debug_ld_app[PROP_VALUE_MAX] = {};
+ GetAppSpecificProperty(debug_ld_app);
+ flags_ |= ParseProperty(debug_ld_app);
+#endif
+}
+
+void LinkerLogger::Log(const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ async_safe_format_log_va_list(ANDROID_LOG_DEBUG, "linker", format, ap);
+ va_end(ap);
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_logger.h
^
|
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include "private/bionic_systrace.h"
+
+#include <android-base/macros.h>
+
+#define __printflike(x, y) __attribute__((__format__(printf, x, y)))
+#define LD_LOG(type, x...) \
+ do { \
+ if (g_linker_logger.IsEnabled(type)) { g_linker_logger.Log(x); g_linker_logger.Log("\n"); } \
+ } while (0)
+
+constexpr const uint32_t kLogErrors = 1 << 0;
+constexpr const uint32_t kLogDlopen = 1 << 1;
+constexpr const uint32_t kLogDlsym = 1 << 2;
+
+class LinkerLogger {
+ public:
+ LinkerLogger() : flags_(0) { }
+
+ void ResetState();
+ void Log(const char* format, ...) __printflike(2, 3);
+
+ uint32_t IsEnabled(uint32_t type) {
+ return flags_ & type;
+ }
+
+ private:
+ uint32_t flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(LinkerLogger);
+};
+
+extern LinkerLogger g_linker_logger;
+extern char** g_argv;
+
+// If the system property debug.ld.greylist_disabled is true, we'll not use the greylist
+// regardless of API level.
+extern bool g_greylist_disabled;
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_main.cpp
^
|
@@ -0,0 +1,818 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hybris_compat.h"
+
+#include "linker_main.h"
+
+#include <link.h>
+#include <sys/auxv.h>
+#include <sys/cdefs-android.h>
+#include <stdarg.h>
+
+#include "linker_debug.h"
+#include "linker_cfi.h"
+#include "linker_gdb_support.h"
+#include "linker_globals.h"
+#include "linker_phdr.h"
+#include "linker_tls.h"
+#include "linker_utils.h"
+
+#include "private/bionic_globals.h"
+#include "private/bionic_tls.h"
+#include "private/KernelArgumentBlock.h"
+
+#include "android-base/unique_fd.h"
+//#include "android-base/strings.h"
+//#include "android-base/stringprintf.h"
+
+#include "linker_utils.h"
+
+#ifdef __ANDROID__
+#include "debuggerd/handler.h"
+#endif
+
+#include <async_safe/log.h>
+#include <bionic/libc_init_common.h>
+#include <bionic/pthread_internal.h>
+
+#include <vector>
+
+extern void __libc_init_globals(KernelArgumentBlock&);
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
+#endif
+
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+extern "C" void _start();
+#endif
+
+static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
+
+static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr)* base, ElfW(Addr)* load_bias);
+
+// These should be preserved static to avoid emitting
+// RELATIVE relocations for the part of the code running
+// before linker links itself.
+
+// TODO (dimtiry): remove somain, rename solist to solist_head
+static soinfo* solist;
+static soinfo* sonext;
+static soinfo* somain; // main process, always the one after libdl_info
+static soinfo* solinker;
+static soinfo* vdso; // vdso if present
+
+void solist_add_soinfo(soinfo* si) {
+ sonext->next = si;
+ sonext = si;
+}
+
+bool solist_remove_soinfo(soinfo* si) {
+ soinfo *prev = nullptr, *trav;
+ for (trav = solist; trav != nullptr; trav = trav->next) {
+ if (trav == si) {
+ break;
+ }
+ prev = trav;
+ }
+
+ if (trav == nullptr) {
+ // si was not in solist
+ PRINT("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
+ return false;
+ }
+
+ // prev will never be null, because the first entry in solist is
+ // always the static libdl_info.
+ CHECK(prev != nullptr);
+ prev->next = si->next;
+ if (si == sonext) {
+ sonext = prev;
+ }
+
+ return true;
+}
+
+soinfo* solist_get_head() {
+// hybris skip the dummy libdl so info
+ return solist->next;
+}
+
+soinfo* solist_get_somain() {
+ return (soinfo*)0xDEADBEEF;
+}
+
+soinfo* solist_get_vdso() {
+ return vdso;
+}
+
+int g_ld_debug_verbosity;
+
+static std::vector<std::string> g_ld_preload_names;
+
+static std::vector<soinfo*> g_ld_preloads;
+
+static void parse_path(const char* path, const char* delimiters,
+ std::vector<std::string>* resolved_paths) {
+ std::vector<std::string> paths;
+ split_path(path, delimiters, &paths);
+ resolve_paths(paths, resolved_paths);
+}
+
+static void parse_LD_LIBRARY_PATH(const char* path) {
+ std::vector<std::string> ld_libary_paths;
+ parse_path(path, ":", &ld_libary_paths);
+ g_default_namespace->set_ld_library_paths(std::move(ld_libary_paths));
+}
+
+static void parse_LD_PRELOAD(const char* path) {
+ g_ld_preload_names.clear();
+ if (path != nullptr) {
+ // We have historically supported ':' as well as ' ' in LD_PRELOAD.
+ g_ld_preload_names = split(path, " :");
+ g_ld_preload_names.erase(std::remove_if(g_ld_preload_names.begin(), g_ld_preload_names.end(),
+ [](const std::string& s) { return s.empty(); }),
+ g_ld_preload_names.end());
+ }
+}
+
+// An empty list of soinfos
+static soinfo_list_t g_empty_list;
+
+static void add_vdso() {
+ ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(getauxval(AT_SYSINFO_EHDR));
+ if (ehdr_vdso == nullptr) {
+ return;
+ }
+
+ soinfo* si = soinfo_alloc(g_default_namespace, "[vdso]", nullptr, 0, 0);
+
+ si->phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
+ si->phnum = ehdr_vdso->e_phnum;
+ si->base = reinterpret_cast<ElfW(Addr)>(ehdr_vdso);
+ si->size = phdr_table_get_load_size(si->phdr, si->phnum);
+ si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
+
+ si->prelink_image();
+ si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr, nullptr);
+ // prevents accidental unloads...
+ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_NODELETE);
+ si->set_linked();
+ si->call_constructors();
+
+ vdso = si;
+}
+
+// Initializes an soinfo's link_map_head field using other fields from the
+// soinfo (phdr, phnum, load_bias).
+static void init_link_map_head(soinfo& info, const char* linker_path) {
+ auto& map = info.link_map_head;
+ map.l_addr = info.load_bias;
+ map.l_name = const_cast<char*>(linker_path);
+ phdr_table_get_dynamic_section(info.phdr, info.phnum, info.load_bias, &map.l_ld, nullptr);
+}
+
+extern "C" int __system_properties_init(void);
+
+struct ExecutableInfo {
+ std::string path;
+ struct stat file_stat;
+ const ElfW(Phdr)* phdr;
+ size_t phdr_count;
+ ElfW(Addr) entry_point;
+};
+
+static ExecutableInfo get_executable_info() {
+ ExecutableInfo result = {};
+
+ if (is_first_stage_init()) {
+ // /proc fs is not mounted when first stage init starts. Therefore we can't
+ // use /proc/self/exe for init.
+ stat("/init", &result.file_stat);
+
+ // /init may be a symlink, so try to read it as such.
+ char path[PATH_MAX];
+ ssize_t path_len = readlink("/init", path, sizeof(path));
+ if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+ result.path = "/init";
+ } else {
+ result.path = std::string(path, path_len);
+ }
+ } else {
+ // Stat "/proc/self/exe" instead of executable_path because
+ // the executable could be unlinked by this point and it should
+ // not cause a crash (see http://b/31084669)
+ if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &result.file_stat)) != 0) {
+ async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
+ }
+ char path[PATH_MAX];
+ ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+ if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+ async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
+ }
+ result.path = std::string(path, path_len);
+ }
+
+ result.phdr = reinterpret_cast<const ElfW(Phdr)*>(getauxval(AT_PHDR));
+ result.phdr_count = getauxval(AT_PHNUM);
+ result.entry_point = getauxval(AT_ENTRY);
+ return result;
+}
+
+#if defined(__LP64__)
+static char kLinkerPath[] = "/system/bin/linker64";
+#else
+static char kLinkerPath[] = "/system/bin/linker";
+#endif
+
+__printflike(1, 2)
+static void __linker_error(const char* fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ va_start(ap, fmt);
+ async_safe_format_log_va_list(ANDROID_LOG_FATAL, "linker", fmt, ap);
+ va_end(ap);
+
+ _exit(EXIT_FAILURE);
+}
+
+static void __linker_cannot_link(const char* argv0) {
+ __linker_error("CANNOT LINK EXECUTABLE \"%s\": %s\n",
+ argv0,
+ linker_get_error_buffer());
+}
+
+// Load an executable. Normally the kernel has already loaded the executable when the linker
+// starts. The linker can be invoked directly on an executable, though, and then the linker must
+// load it. This function doesn't load dependencies or resolve relocations.
+static ExecutableInfo load_executable(const char* orig_path) {
+ ExecutableInfo result = {};
+
+ if (orig_path[0] != '/') {
+ __linker_error("error: expected absolute path: \"%s\"\n", orig_path);
+ }
+
+ off64_t file_offset;
+ android::base::unique_fd fd(open_executable(orig_path, &file_offset, &result.path));
+ if (fd.get() == -1) {
+ __linker_error("error: unable to open file \"%s\"\n", orig_path);
+ }
+
+ if (TEMP_FAILURE_RETRY(fstat(fd.get(), &result.file_stat)) == -1) {
+ __linker_error("error: unable to stat \"%s\": %s\n", result.path.c_str(), strerror(errno));
+ }
+
+ ElfReader elf_reader;
+ if (!elf_reader.Read(result.path.c_str(), fd.get(), file_offset, result.file_stat.st_size)) {
+ __linker_error("error: %s\n", linker_get_error_buffer());
+ }
+ address_space_params address_space;
+ if (!elf_reader.Load(&address_space)) {
+ __linker_error("error: %s\n", linker_get_error_buffer());
+ }
+
+ result.phdr = elf_reader.loaded_phdr();
+ result.phdr_count = elf_reader.phdr_count();
+ result.entry_point = elf_reader.entry_point();
+ return result;
+}
+
+static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) {
+ ProtectedDataGuard guard;
+
+#if TIMING
+ struct timeval t0, t1;
+ gettimeofday(&t0, 0);
+#endif
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ // Sanitize the environment.
+ __libc_init_AT_SECURE(args.envp);
+
+ // Initialize system properties
+ __system_properties_init(); // may use 'environ'
+
+ // Register the debuggerd signal handler.
+#ifdef __ANDROID__
+ debuggerd_callbacks_t callbacks = {
+ .get_abort_message = []() {
+ return __libc_shared_globals()->abort_msg;
+ },
+ .post_dump = ¬ify_gdb_of_libraries,
+ };
+ debuggerd_init(&callbacks);
+#endif
+#endif
+
+ g_linker_logger.ResetState();
+
+ // Get a few environment variables.
+ const char* LD_DEBUG = getenv("LD_DEBUG");
+ if (LD_DEBUG != nullptr) {
+ g_ld_debug_verbosity = atoi(LD_DEBUG);
+ }
+
+#if defined(__LP64__)
+ INFO("[ Android dynamic linker (64-bit) ]");
+#else
+ INFO("[ Android dynamic linker (32-bit) ]");
+#endif
+
+ // These should have been sanitized by __libc_init_AT_SECURE, but the test
+ // doesn't cost us anything.
+ const char* ldpath_env = nullptr;
+ const char* ldpreload_env = nullptr;
+ if (!getauxval(AT_SECURE)) {
+ ldpath_env = getenv("LD_LIBRARY_PATH");
+ if (ldpath_env != nullptr) {
+ INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
+ }
+ ldpreload_env = getenv("LD_PRELOAD");
+ if (ldpreload_env != nullptr) {
+ INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
+ }
+ }
+
+ const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
+ get_executable_info();
+
+ // Assign to a static variable for the sake of the debug map, which needs
+ // a C-style string to last until the program exits.
+ static std::string exe_path = exe_info.path;
+
+ INFO("[ Linking executable \"%s\" ]", exe_path.c_str());
+
+ // Initialize the main exe's soinfo.
+ soinfo* si = soinfo_alloc(g_default_namespace,
+ exe_path.c_str(), &exe_info.file_stat,
+ 0, RTLD_GLOBAL);
+ somain = si;
+ si->phdr = exe_info.phdr;
+ si->phnum = exe_info.phdr_count;
+ get_elf_base_from_phdr(si->phdr, si->phnum, &si->base, &si->load_bias);
+ si->size = phdr_table_get_load_size(si->phdr, si->phnum);
+ si->dynamic = nullptr;
+ si->set_main_executable();
+ init_link_map_head(*si, exe_path.c_str());
+
+ // Register the main executable and the linker upfront to have
+ // gdb aware of them before loading the rest of the dependency
+ // tree.
+ //
+ // gdb expects the linker to be in the debug shared object list.
+ // Without this, gdb has trouble locating the linker's ".text"
+ // and ".plt" sections. Gdb could also potentially use this to
+ // relocate the offset of our exported 'rtld_db_dlactivity' symbol.
+ //
+ insert_link_map_into_debug_map(&si->link_map_head);
+ insert_link_map_into_debug_map(&solinker->link_map_head);
+
+ add_vdso();
+
+ ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
+
+ // We haven't supported non-PIE since Lollipop for security reasons.
+ if (elf_hdr->e_type != ET_DYN) {
+ // We don't use async_safe_fatal here because we don't want a tombstone:
+ // even after several years we still find ourselves on app compatibility
+ // investigations because some app's trying to launch an executable that
+ // hasn't worked in at least three years, and we've "helpfully" dropped a
+ // tombstone for them. The tombstone never provided any detail relevant to
+ // fixing the problem anyway, and the utility of drawing extra attention
+ // to the problem is non-existent at this late date.
+ async_safe_format_fd(STDERR_FILENO,
+ "\"%s\": error: Android 5.0 and later only support "
+ "position-independent executables (-fPIE).\n",
+ g_argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
+ parse_LD_LIBRARY_PATH(ldpath_env);
+ parse_LD_PRELOAD(ldpreload_env);
+
+ std::vector<android_namespace_t*> namespaces = init_default_namespaces(exe_path.c_str());
+
+ if (!si->prelink_image()) __linker_cannot_link(g_argv[0]);
+
+ // add somain to global group
+ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
+ // ... and add it to all other linked namespaces
+ for (auto linked_ns : namespaces) {
+ if (linked_ns != g_default_namespace) {
+ linked_ns->add_soinfo(somain);
+ somain->add_secondary_namespace(linked_ns);
+ }
+ }
+
+ linker_setup_exe_static_tls(g_argv[0]);
+
+ // Load ld_preloads and dependencies.
+ std::vector<const char*> needed_library_name_list;
+ size_t ld_preloads_count = 0;
+
+ for (const auto& ld_preload_name : g_ld_preload_names) {
+ needed_library_name_list.push_back(ld_preload_name.c_str());
+ ++ld_preloads_count;
+ }
+
+ for_each_dt_needed(si, [&](const char* name) {
+ needed_library_name_list.push_back(name);
+ });
+
+ const char** needed_library_names = &needed_library_name_list[0];
+ size_t needed_libraries_count = needed_library_name_list.size();
+
+ if (needed_libraries_count > 0 &&
+ !find_libraries(g_default_namespace,
+ si,
+ needed_library_names,
+ needed_libraries_count,
+ nullptr,
+ &g_ld_preloads,
+ ld_preloads_count,
+ RTLD_GLOBAL,
+ nullptr,
+ true /* add_as_children */,
+ true /* search_linked_namespaces */,
+ &namespaces)) {
+ __linker_cannot_link(g_argv[0]);
+ } else if (needed_libraries_count == 0) {
+ if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr, nullptr)) {
+ __linker_cannot_link(g_argv[0]);
+ }
+ si->increment_ref_count();
+ }
+
+ linker_finalize_static_tls();
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+ __libc_init_main_thread_final();
+#endif
+
+ if (!get_cfi_shadow()->InitialLinkDone(solist)) __linker_cannot_link(g_argv[0]);
+
+ si->call_pre_init_constructors();
+ si->call_constructors();
+
+#if TIMING
+ gettimeofday(&t1, nullptr);
+ PRINT("LINKER TIME: %s: %d microseconds", g_argv[0], (int) (
+ (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) -
+ (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec)));
+#endif
+#if STATS
+ PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol", g_argv[0],
+ linker_stats.count[kRelocAbsolute],
+ linker_stats.count[kRelocRelative],
+ linker_stats.count[kRelocCopy],
+ linker_stats.count[kRelocSymbol]);
+#endif
+#if COUNT_PAGES
+ {
+ unsigned n;
+ unsigned i;
+ unsigned count = 0;
+ for (n = 0; n < 4096; n++) {
+ if (bitmask[n]) {
+ unsigned x = bitmask[n];
+#if defined(__LP64__)
+ for (i = 0; i < 32; i++) {
+#else
+ for (i = 0; i < 8; i++) {
+#endif
+ if (x & 1) {
+ count++;
+ }
+ x >>= 1;
+ }
+ }
+ }
+ PRINT("PAGES MODIFIED: %s: %d (%dKB)", g_argv[0], count, count * 4);
+ }
+#endif
+
+#if TIMING || STATS || COUNT_PAGES
+ fflush(stdout);
+#endif
+
+ // We are about to hand control over to the executable loaded. We don't want
+ // to leave dirty pages behind unnecessarily.
+ purge_unused_memory();
+
+ ElfW(Addr) entry = exe_info.entry_point;
+ TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
+ return entry;
+}
+
+/* Compute the load-bias of an existing executable. This shall only
+ * be used to compute the load bias of an executable or shared library
+ * that was loaded by the kernel itself.
+ *
+ * Input:
+ * elf -> address of ELF header, assumed to be at the start of the file.
+ * Return:
+ * load bias, i.e. add the value of any p_vaddr in the file to get
+ * the corresponding address in memory.
+ */
+static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf) {
+ ElfW(Addr) offset = elf->e_phoff;
+ const ElfW(Phdr)* phdr_table =
+ reinterpret_cast<const ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(elf) + offset);
+ const ElfW(Phdr)* phdr_end = phdr_table + elf->e_phnum;
+
+ for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_end; phdr++) {
+ if (phdr->p_type == PT_LOAD) {
+ return reinterpret_cast<ElfW(Addr)>(elf) + phdr->p_offset - phdr->p_vaddr;
+ }
+ }
+ return 0;
+}
+
+/* Find the load bias and base address of an executable or shared object loaded
+ * by the kernel. The ELF file's PHDR table must have a PT_PHDR entry.
+ *
+ * A VDSO doesn't have a PT_PHDR entry in its PHDR table.
+ */
+static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr)* base, ElfW(Addr)* load_bias) {
+ for (size_t i = 0; i < phdr_count; ++i) {
+ if (phdr_table[i].p_type == PT_PHDR) {
+ *load_bias = reinterpret_cast<ElfW(Addr)>(phdr_table) - phdr_table[i].p_vaddr;
+ *base = reinterpret_cast<ElfW(Addr)>(phdr_table) - phdr_table[i].p_offset;
+ return;
+ }
+ }
+ async_safe_fatal("Could not find a PHDR: broken executable?");
+}
+
+#if defined(__i386__)
+__LIBC_HIDDEN__ void* __libc_sysinfo;
+#endif
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+__LIBC_HIDDEN__ __attribute__((__naked__)) void __libc_int0x80() {
+ __asm__ volatile("int $0x80; ret");
+}
+// Detect an attempt to run the linker on itself. e.g.:
+// /system/bin/linker64 /system/bin/linker64
+// Use priority-1 to run this constructor before other constructors.
+__attribute__((constructor(1))) static void detect_self_exec() {
+ // Normally, the linker initializes the auxv global before calling its
+ // constructors. If the linker loads itself, though, the first loader calls
+ // the second loader's constructors before calling __linker_init.
+ if (__libc_shared_globals()->auxv != nullptr) {
+ return;
+ }
+#if defined(__i386__)
+ // We don't have access to the auxv struct from here, so use the int 0x80
+ // fallback.
+ __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
+#endif
+ __linker_error("error: linker cannot load itself\n");
+}
+#endif
+
+static ElfW(Addr) __attribute__((noinline))
+__linker_init_post_relocation(KernelArgumentBlock& args, soinfo& linker_so);
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+/*
+ * This is the entry point for the linker, called from begin.S. This
+ * method is responsible for fixing the linker's own relocations, and
+ * then calling __linker_init_post_relocation().
+ *
+ * Because this method is called before the linker has fixed it's own
+ * relocations, any attempt to reference an extern variable, extern
+ * function, or other GOT reference will generate a segfault.
+ */
+extern "C" ElfW(Addr) __linker_init(void* raw_args) {
+ // Initialize TLS early so system calls and errno work.
+ KernelArgumentBlock args(raw_args);
+ bionic_tcb temp_tcb = {};
+ __libc_init_main_thread_early(args, &temp_tcb);
+
+ // When the linker is run by itself (rather than as an interpreter for
+ // another program), AT_BASE is 0.
+ ElfW(Addr) linker_addr = getauxval(AT_BASE);
+ if (linker_addr == 0) {
+ // The AT_PHDR and AT_PHNUM aux values describe this linker instance, so use
+ // the phdr to find the linker's base address.
+ ElfW(Addr) load_bias;
+ get_elf_base_from_phdr(
+ reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
+ &linker_addr, &load_bias);
+ }
+
+ ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
+ ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
+
+ soinfo tmp_linker_so(nullptr, nullptr, nullptr, 0, 0);
+
+ tmp_linker_so.base = linker_addr;
+ tmp_linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
+ tmp_linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);
+ tmp_linker_so.dynamic = nullptr;
+ tmp_linker_so.phdr = phdr;
+ tmp_linker_so.phnum = elf_hdr->e_phnum;
+ tmp_linker_so.set_linker_flag();
+
+ // Prelink the linker so we can access linker globals.
+ if (!tmp_linker_so.prelink_image()) __linker_cannot_link(args.argv[0]);
+
+ // This might not be obvious... The reasons why we pass g_empty_list
+ // in place of local_group here are (1) we do not really need it, because
+ // linker is built with DT_SYMBOLIC and therefore relocates its symbols against
+ // itself without having to look into local_group and (2) allocators
+ // are not yet initialized, and therefore we cannot use linked_list.push_*
+ // functions at this point.
+ if (!tmp_linker_so.link_image(g_empty_list, g_empty_list, nullptr, nullptr)) __linker_cannot_link(args.argv[0]);
+
+ return __linker_init_post_relocation(args, tmp_linker_so);
+}
+#endif
+
+#ifdef DISABLED_FOR_HYBRIS_SUPPORT
+/*
+ * This code is called after the linker has linked itself and fixed its own
+ * GOT. It is safe to make references to externs and other non-local data at
+ * this point. The compiler sometimes moves GOT references earlier in a
+ * function, so avoid inlining this function (http://b/80503879).
+ */
+static ElfW(Addr) __attribute__((noinline))
+__linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) {
+ // Finish initializing the main thread.
+ __libc_init_main_thread_late();
+
+ // We didn't protect the linker's RELRO pages in link_image because we
+ // couldn't make system calls on x86 at that point, but we can now...
+ if (!tmp_linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);
+
+ // Initialize the linker's static libc's globals
+ __libc_init_globals(args);
+
+ // Initialize the linker's own global variables
+ tmp_linker_so.call_constructors();
+
+ // When the linker is run directly rather than acting as PT_INTERP, parse
+ // arguments and determine the executable to load. When it's instead acting
+ // as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the
+ // linker's _start.
+ const char* exe_to_load = nullptr;
+ if (getauxval(AT_ENTRY) == reinterpret_cast<uintptr_t>(&_start)) {
+ if (args.argc <= 1 || !strcmp(args.argv[1], "--help")) {
+ async_safe_format_fd(STDOUT_FILENO,
+ "Usage: %s program [arguments...]\n"
+ " %s path.zip!/program [arguments...]\n"
+ "\n"
+ "A helper program for linking dynamic executables. Typically, the kernel loads\n"
+ "this program because it's the PT_INTERP of a dynamic executable.\n"
+ "\n"
+ "This program can also be run directly to load and run a dynamic executable. The\n"
+ "executable can be inside a zip file if it's stored uncompressed and at a\n"
+ "page-aligned offset.\n",
+ args.argv[0], args.argv[0]);
+ exit(0);
+ }
+ exe_to_load = args.argv[1];
+ __libc_shared_globals()->initial_linker_arg_count = 1;
+ }
+
+ // store argc/argv/envp to use them for calling constructors
+ g_argc = args.argc - __libc_shared_globals()->initial_linker_arg_count;
+ g_argv = args.argv + __libc_shared_globals()->initial_linker_arg_count;
+ g_envp = args.envp;
+ __libc_shared_globals()->init_progname = g_argv[0];
+
+ // Initialize static variables. Note that in order to
+ // get correct libdl_info we need to call constructors
+ // before get_libdl_info().
+ sonext = solist = solinker = get_libdl_info(kLinkerPath, tmp_linker_so);
+ g_default_namespace->add_soinfo(solinker);
+ init_link_map_head(*solinker, kLinkerPath);
+
+ ElfW(Addr) start_address = linker_main(args, exe_to_load);
+
+ INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
+
+ // Return the address that the calling assembly stub should jump to.
+ return start_address;
+}
+#endif
+
+
+static void generate_tmpsoinfo(soinfo& tmp_linker_so) {
+ tmp_linker_so.base = (ElfW(Addr))nullptr;
+ tmp_linker_so.size = 0;
+ tmp_linker_so.load_bias = 0;
+ tmp_linker_so.dynamic = nullptr;
+ tmp_linker_so.phdr = nullptr;
+ tmp_linker_so.phnum = 0;
+ tmp_linker_so.set_linker_flag();
+
+ DEBUG("tmp_linker_so's load_bias=%p \n", tmp_linker_so.load_bias);
+
+ // Prelink the linker so we can access linker globals.
+// if (!tmp_linker_so.prelink_image()) {
+// PRINT("can't prelink self:ret\n");
+// };
+
+ //tmp_linker_so.call_constructors();
+}
+
+static const char* get_executable_path() {
+ static std::string executable_path;
+ if (executable_path.empty()) {
+ char path[PATH_MAX];
+ ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+ if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+ async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
+ }
+ executable_path = std::string(path, path_len);
+ }
+
+ return executable_path.c_str();
+}
+
+void* (*_get_hooked_symbol)(const char *sym, const char *requester);
+void *(*_create_wrapper)(const char *symbol, void *function, int wrapper_type);
+#ifdef WANT_ARM_TRACING
+extern "C" void android_linker_init(int sdk_version, void* (*get_hooked_symbol)(const char*, const char*), int enable_linker_gdb_support, void *(create_wrapper)(const char*, void*, int)) {
+#else
+extern "C" void android_linker_init(int sdk_version, void* (*get_hooked_symbol)(const char*, const char*), int enable_linker_gdb_support) {
+#endif
+ // Get a few environment variables.
+ const char* LD_DEBUG = getenv("HYBRIS_LD_DEBUG");
+ if (LD_DEBUG != nullptr) {
+ g_ld_debug_verbosity = atoi(LD_DEBUG);
+ }
+
+ const char* ldpath_env = nullptr;
+ const char* ldpreload_env = nullptr;
+ if (!getauxval(AT_SECURE)) {
+ ldpath_env = getenv("HYBRIS_LD_LIBRARY_PATH");
+ ldpreload_env = getenv("HYBRIS_LD_PRELOAD");
+ }
+
+ if (ldpath_env)
+ parse_LD_LIBRARY_PATH(ldpath_env);
+ else
+ parse_LD_LIBRARY_PATH(DEFAULT_HYBRIS_LD_LIBRARY_PATH);
+ parse_LD_PRELOAD(ldpreload_env);
+
+ DEBUG("sdk_version %d\n", sdk_version);
+
+ if (sdk_version > 0)
+ set_application_target_sdk_version(sdk_version);
+
+ _get_hooked_symbol = get_hooked_symbol;
+ _linker_enable_gdb_support = enable_linker_gdb_support;
+#ifdef WANT_ARM_TRACING
+ _create_wrapper = create_wrapper;
+#endif
+
+ soinfo tmp_linker_so(nullptr, nullptr, nullptr, 0, 0);
+ generate_tmpsoinfo(tmp_linker_so);
+
+ sonext = solist = get_libdl_info(kLinkerPath, tmp_linker_so);
+
+ add_vdso();
+ //init_link_map_head(tmp_linker_so, kLinkerPath);
+ //insert_link_map_into_debug_map(&tmp_linker_so.link_map_head);
+
+ DEBUG("sdk_version %d\n", sdk_version);
+
+ init_default_namespaces(get_executable_path());
+ DEBUG("init_default_namespaces %d\n", sdk_version);
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_main.h
^
|
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <android/dlext.h>
+
+#include <unordered_map>
+#include <vector>
+
+#include "linker_namespaces.h"
+#include "linker_soinfo.h"
+
+class ProtectedDataGuard {
+ public:
+ ProtectedDataGuard();
+ ~ProtectedDataGuard();
+
+ private:
+ void protect_data(int protection);
+ static size_t ref_count_;
+};
+
+class ElfReader;
+
+std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path);
+soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
+ const struct stat* file_stat, off64_t file_offset,
+ uint32_t rtld_flags);
+
+bool find_libraries(android_namespace_t* ns,
+ soinfo* start_with,
+ const char* const library_names[],
+ size_t library_names_count,
+ soinfo* soinfos[],
+ std::vector<soinfo*>* ld_preloads,
+ size_t ld_preloads_count,
+ int rtld_flags,
+ const android_dlextinfo* extinfo,
+ bool add_as_children,
+ bool search_linked_namespaces,
+ std::vector<android_namespace_t*>* namespaces = nullptr);
+
+void solist_add_soinfo(soinfo* si);
+bool solist_remove_soinfo(soinfo* si);
+soinfo* solist_get_head();
+soinfo* solist_get_somain();
+soinfo* solist_get_vdso();
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_mapped_file_fragment.cpp
^
|
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_mapped_file_fragment.h"
+#include "linker_debug.h"
+#include "linker_utils.h"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+MappedFileFragment::MappedFileFragment() : map_start_(nullptr), map_size_(0),
+ data_(nullptr), size_ (0)
+{ }
+
+MappedFileFragment::~MappedFileFragment() {
+ if (map_start_ != nullptr) {
+ munmap(map_start_, map_size_);
+ }
+}
+
+bool MappedFileFragment::Map(int fd, off64_t base_offset, size_t elf_offset, size_t size) {
+ off64_t offset;
+ CHECK(safe_add(&offset, base_offset, elf_offset));
+
+ off64_t page_min = page_start(offset);
+ off64_t end_offset;
+
+ CHECK(safe_add(&end_offset, offset, size));
+ CHECK(safe_add(&end_offset, end_offset, page_offset(offset)));
+
+ size_t map_size = static_cast<size_t>(end_offset - page_min);
+ CHECK(map_size >= size);
+
+ uint8_t* map_start = static_cast<uint8_t*>(
+ mmap64(nullptr, map_size, PROT_READ, MAP_PRIVATE, fd, page_min));
+
+ if (map_start == MAP_FAILED) {
+ return false;
+ }
+
+ map_start_ = map_start;
+ map_size_ = map_size;
+
+ data_ = map_start + page_offset(offset);
+ size_ = size;
+
+ return true;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_mapped_file_fragment.h
^
|
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <unistd.h>
+
+#include <android-base/macros.h>
+
+class MappedFileFragment {
+ public:
+ MappedFileFragment();
+ ~MappedFileFragment();
+
+ bool Map(int fd, off64_t base_offset, size_t elf_offset, size_t size);
+
+ void* data() const { return data_; }
+ size_t size() const { return size_; }
+ private:
+ void* map_start_;
+ size_t map_size_;
+ void* data_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(MappedFileFragment);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_memory.cpp
^
|
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "private/bionic_allocator.h"
+
+#include <stdlib.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <atomic>
+
+#include <async_safe/log.h>
+#include <sys/syscall.h>
+
+#define gettid() syscall(SYS_gettid)
+
+#if DISABLED_FOR_HYBRIS_SUPPORT
+static BionicAllocator g_bionic_allocator;
+static std::atomic<pid_t> fallback_tid(0);
+
+// Used by libdebuggerd_handler to switch allocators during a crash dump, in
+// case the linker heap is corrupted. Do not use this function.
+extern "C" bool __linker_enable_fallback_allocator() {
+ pid_t expected = 0;
+ return fallback_tid.compare_exchange_strong(expected, gettid());
+}
+
+extern "C" void __linker_disable_fallback_allocator() {
+ pid_t previous = fallback_tid.exchange(0);
+ if (previous == 0) {
+ async_safe_fatal("attempted to disable unused fallback allocator");
+ } else if (previous != gettid()) {
+ async_safe_fatal("attempted to disable fallback allocator in use by another thread (%d)",
+ previous);
+ }
+}
+
+static BionicAllocator& get_fallback_allocator() {
+ static BionicAllocator fallback_allocator;
+ return fallback_allocator;
+}
+
+#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
+
+static BionicAllocator& get_allocator() {
+ if (__predict_false(fallback_tid) && __predict_false(gettid() == fallback_tid)) {
+ return get_fallback_allocator();
+ }
+ return g_bionic_allocator;
+}
+
+void* malloc(size_t byte_count) {
+ return get_allocator().alloc(byte_count);
+}
+
+void* calloc(size_t item_count, size_t item_size) {
+ return get_allocator().alloc(item_count*item_size);
+}
+
+void* realloc(void* p, size_t byte_count) {
+ return get_allocator().realloc(p, byte_count);
+}
+
+void* reallocarray(void* p, size_t item_count, size_t item_size) {
+ size_t byte_count;
+ if (__builtin_mul_overflow(item_count, item_size, &byte_count)) {
+ errno = ENOMEM;
+ return nullptr;
+ }
+ return get_allocator().realloc(p, byte_count);
+}
+
+void free(void* ptr) {
+ get_allocator().free(ptr);
+}
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_mips.cpp
^
|
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(__LP64__) && __mips_isa_rev >= 5
+#include <sys/prctl.h>
+#endif
+
+#include "linker.h"
+#include "linker_debug.h"
+#include "linker_globals.h"
+#include "linker_phdr.h"
+#include "linker_relocs.h"
+#include "linker_reloc_iterators.h"
+#include "linker_sleb128.h"
+#include "linker_soinfo.h"
+
+template bool soinfo::relocate<plain_reloc_iterator>(const VersionTracker& version_tracker,
+ plain_reloc_iterator&& rel_iterator,
+ const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group);
+
+template bool soinfo::relocate<packed_reloc_iterator<sleb128_decoder>>(
+ const VersionTracker& version_tracker,
+ packed_reloc_iterator<sleb128_decoder>&& rel_iterator,
+ const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group);
+
+template <typename ElfRelIteratorT>
+bool soinfo::relocate(const VersionTracker& version_tracker,
+ ElfRelIteratorT&& rel_iterator,
+ const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group) {
+ for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
+ const auto rel = rel_iterator.next();
+
+ if (rel == nullptr) {
+ return false;
+ }
+
+ ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);
+ ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);
+
+ ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
+ ElfW(Addr) sym_addr = 0;
+ const char* sym_name = nullptr;
+
+ DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
+ if (type == R_GENERIC_NONE) {
+ continue;
+ }
+
+ const ElfW(Sym)* s = nullptr;
+ soinfo* lsi = nullptr;
+
+ if (sym != 0) {
+ sym_name = get_string(symtab_[sym].st_name);
+ const version_info* vi = nullptr;
+
+ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+ return false;
+ }
+
+ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ return false;
+ }
+
+ if (s == nullptr) {
+ // mips does not support relocation with weak-undefined symbols
+ DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...",
+ sym_name, get_realpath());
+ return false;
+ } else {
+ // We got a definition.
+ sym_addr = lsi->resolve_symbol_address(s);
+ }
+ count_relocation(kRelocSymbol);
+ }
+
+ switch (type) {
+ case R_MIPS_REL32:
+#if defined(__LP64__)
+ // MIPS Elf64_Rel entries contain compound relocations
+ // We only handle the R_MIPS_NONE|R_MIPS_64|R_MIPS_REL32 case
+ if (ELF64_R_TYPE2(rel->r_info) != R_MIPS_64 ||
+ ELF64_R_TYPE3(rel->r_info) != R_MIPS_NONE) {
+ DL_ERR("Unexpected compound relocation type:%d type2:%d type3:%d @ %p (%zu)",
+ type, static_cast<unsigned>(ELF64_R_TYPE2(rel->r_info)),
+ static_cast<unsigned>(ELF64_R_TYPE3(rel->r_info)), rel, idx);
+ return false;
+ }
+#endif
+ count_relocation(s == nullptr ? kRelocAbsolute : kRelocRelative);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO REL32 %08zx <- %08zx %s", static_cast<size_t>(reloc),
+ static_cast<size_t>(sym_addr), sym_name ? sym_name : "*SECTIONHDR*");
+ if (s != nullptr) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
+ } else {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) += load_bias;
+ }
+ break;
+ default:
+ DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
+ const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group) {
+ ElfW(Addr)** got = plt_got_;
+ if (got == nullptr) {
+ return true;
+ }
+
+ // got[0] is the address of the lazy resolver function.
+ // got[1] may be used for a GNU extension.
+ // FIXME: maybe this should be in a separate routine?
+ if ((flags_ & FLAG_LINKER) == 0) {
+ size_t g = 1;
+ // Check for the high bit to determine whether to skip got[1]
+ if (reinterpret_cast<intptr_t>(got[g]) < 0) {
+ g++;
+ }
+ // Relocate the local GOT entries.
+ for (; g < mips_local_gotno_; g++) {
+ got[g] = reinterpret_cast<ElfW(Addr)*>(reinterpret_cast<uintptr_t>(got[g]) + load_bias);
+ }
+ }
+
+ // Now for the global GOT entries...
+ got = plt_got_ + mips_local_gotno_;
+ for (ElfW(Word) sym = mips_gotsym_; sym < mips_symtabno_; sym++, got++) {
+ // This is an undefined reference... try to locate it.
+ const ElfW(Sym)* local_sym = symtab_ + sym;
+ const char* sym_name = get_string(local_sym->st_name);
+ soinfo* lsi = nullptr;
+ const ElfW(Sym)* s = nullptr;
+
+ ElfW(Word) st_visibility = (local_sym->st_other & 0x3);
+
+ if (st_visibility == STV_DEFAULT) {
+ const version_info* vi = nullptr;
+
+ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+ return false;
+ }
+
+ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ return false;
+ }
+ } else if (st_visibility == STV_PROTECTED) {
+ if (local_sym->st_value == 0) {
+ DL_ERR("%s: invalid symbol \"%s\" (PROTECTED/UNDEFINED) ",
+ get_realpath(), sym_name);
+ return false;
+ }
+ s = local_sym;
+ lsi = this;
+ } else {
+ DL_ERR("%s: invalid symbol \"%s\" visibility: 0x%x",
+ get_realpath(), sym_name, st_visibility);
+ return false;
+ }
+
+ if (s == nullptr) {
+ // We only allow an undefined symbol if this is a weak reference.
+ if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) {
+ DL_ERR("%s: cannot locate \"%s\"...", get_realpath(), sym_name);
+ return false;
+ }
+ *got = 0;
+ } else {
+ // FIXME: is this sufficient?
+ // For reference see NetBSD link loader
+ // http://cvsweb.netbsd.org/bsdweb.cgi/src/libexec/ld.elf_so/arch/mips/mips_reloc.c?rev=1.53&content-type=text/x-cvsweb-markup
+ *got = reinterpret_cast<ElfW(Addr)*>(lsi->resolve_symbol_address(s));
+ }
+ }
+ return true;
+}
+
+#if !defined(__LP64__)
+
+// Checks for mips32's various floating point abis.
+// (Mips64 Android has a single floating point abi and doesn't need any checks)
+
+// Linux kernel has declarations similar to the following
+// in <linux>/arch/mips/include/asm/elf.h,
+// but that non-uapi internal header file will never be imported
+// into bionic's kernel headers.
+
+#define PT_MIPS_ABIFLAGS 0x70000003 // is .MIPS.abiflags segment
+
+struct mips_elf_abiflags_v0 {
+ uint16_t version; // version of this structure
+ uint8_t isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size;
+ uint8_t fp_abi; // mips32 ABI variants for floating point
+ uint32_t isa_ext, ases, flags1, flags2;
+};
+
+// Bits of flags1:
+#define MIPS_AFL_FLAGS1_ODDSPREG 1 // Uses odd-numbered single-prec fp regs
+
+// Some values of fp_abi: via compiler flag:
+#define MIPS_ABI_FP_ANY 0 // Not tagged or not using any ABIs affected by the differences.
+#define MIPS_ABI_FP_DOUBLE 1 // -mdouble-float
+#define MIPS_ABI_FP_XX 5 // -mfpxx
+#define MIPS_ABI_FP_64A 7 // -mips32r* -mfp64 -mno-odd-spreg
+
+#if __mips_isa_rev >= 5
+static bool mips_fre_mode_on = false; // have set FRE=1 mode for process
+#endif
+
+bool soinfo::mips_check_and_adjust_fp_modes() {
+ mips_elf_abiflags_v0* abiflags = nullptr;
+ int mips_fpabi;
+
+ // Find soinfo's optional .MIPS.abiflags segment
+ for (size_t i = 0; i<phnum; ++i) {
+ const ElfW(Phdr)& ph = phdr[i];
+ if (ph.p_type == PT_MIPS_ABIFLAGS) {
+ if (ph.p_filesz < sizeof (mips_elf_abiflags_v0)) {
+ DL_ERR("Corrupt PT_MIPS_ABIFLAGS header found \"%s\"", get_realpath());
+ return false;
+ }
+ abiflags = reinterpret_cast<mips_elf_abiflags_v0*>(ph.p_vaddr + load_bias);
+ break;
+ }
+ }
+
+ // FP ABI-variant compatibility checks for MIPS o32 ABI
+ if (abiflags == nullptr) {
+ // Old compilers lack the new abiflags section.
+ // These compilers used -mfp32 -mdouble-float -modd-spreg defaults,
+ // ie FP32 aka DOUBLE, using odd-numbered single-prec regs
+ mips_fpabi = MIPS_ABI_FP_DOUBLE;
+ } else {
+ mips_fpabi = abiflags->fp_abi;
+ if ( (abiflags->flags1 & MIPS_AFL_FLAGS1_ODDSPREG)
+ && (mips_fpabi == MIPS_ABI_FP_XX ||
+ mips_fpabi == MIPS_ABI_FP_64A ) ) {
+ // Android supports fewer cases than Linux
+ DL_ERR("Unsupported odd-single-prec FloatPt reg uses in \"%s\"",
+ get_realpath());
+ return false;
+ }
+ }
+ if (!(mips_fpabi == MIPS_ABI_FP_DOUBLE ||
+#if __mips_isa_rev >= 5
+ mips_fpabi == MIPS_ABI_FP_64A ||
+#endif
+ mips_fpabi == MIPS_ABI_FP_ANY ||
+ mips_fpabi == MIPS_ABI_FP_XX )) {
+ DL_ERR("Unsupported MIPS32 FloatPt ABI %d found in \"%s\"",
+ mips_fpabi, get_realpath());
+ return false;
+ }
+
+#if __mips_isa_rev >= 5
+ // Adjust process's FR Emulation mode, if needed
+ //
+ // On Mips R5 & R6, Android runs continuously in FR=1 64bit-fpreg mode.
+ // NDK mips32 apps compiled with old compilers generate FP32 code
+ // which expects FR=0 32-bit fp registers.
+ // NDK mips32 apps compiled with newer compilers generate modeless
+ // FPXX code which runs on both FR=0 and FR=1 modes.
+ // Android itself is compiled in FP64A which requires FR=1 mode.
+ // FP32, FPXX, and FP64A all interlink okay, without dynamic FR mode
+ // changes during calls. For details, see
+ // http://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
+ // Processes containing FR32 FR=0 code are run via kernel software assist,
+ // which maps all odd-numbered single-precision reg refs onto the
+ // upper half of the paired even-numbered double-precision reg.
+ // FRE=1 triggers traps to the kernel's emulator on every single-precision
+ // fp op (for both odd and even-numbered registers).
+ // Turning on FRE=1 traps is done at most once per process, simultanously
+ // for all threads of that process, when dlopen discovers FP32 code.
+ // The kernel repacks threads' registers when FRE mode is turn on or off.
+ // These asynchronous adjustments are wrong if any thread was executing
+ // FPXX code using odd-numbered single-precision regs.
+ // Current Android compilers default to the -mno-oddspreg option,
+ // and this requirement is checked by Android's dlopen.
+ // So FRE can always be safely turned on for FP32, anytime.
+ // Deferred enhancement: Allow loading of odd-spreg FPXX modules.
+
+ if (mips_fpabi == MIPS_ABI_FP_DOUBLE && !mips_fre_mode_on) {
+ // Turn on FRE mode, which emulates mode-sensitive FR=0 code on FR=1
+ // register files, by trapping to kernel on refs to single-precision regs
+ if (prctl(PR_SET_FP_MODE, PR_FP_MODE_FR|PR_FP_MODE_FRE)) {
+ DL_ERR("Kernel or cpu failed to set FRE mode required for running \"%s\"",
+ get_realpath());
+ return false;
+ }
+ DL_WARN("Using FRE=1 mode to run \"%s\"", get_realpath());
+ mips_fre_mode_on = true; // Avoid future redundant mode-switch calls
+ // FRE mode is never turned back off.
+ // Deferred enhancement:
+ // Reset FRE mode when dlclose() removes all FP32 modules
+ }
+#else
+ // Android runs continuously in FR=0 32bit-fpreg mode.
+#endif // __mips_isa_rev
+ return true;
+}
+
+#endif // __LP64___
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_namespaces.cpp
^
|
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_namespaces.h"
+#include "linker_globals.h"
+#include "linker_soinfo.h"
+#include "linker_utils.h"
+
+#include <dlfcn.h>
+#include <algorithm>
+
+bool android_namespace_t::is_accessible(const std::string& file) {
+ if (!is_isolated_) {
+ return true;
+ }
+
+ if (!whitelisted_libs_.empty()) {
+ const char *lib_name = basename(file.c_str());
+ if (std::find(whitelisted_libs_.begin(), whitelisted_libs_.end(),
+ lib_name) == whitelisted_libs_.end()) {
+ return false;
+ }
+ }
+
+ for (const auto& dir : ld_library_paths_) {
+ if (file_is_in_dir(file, dir)) {
+ return true;
+ }
+ }
+
+ for (const auto& dir : default_library_paths_) {
+ if (file_is_in_dir(file, dir)) {
+ return true;
+ }
+ }
+
+ for (const auto& dir : permitted_paths_) {
+ if (file_is_under_dir(file, dir)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool android_namespace_t::is_accessible(soinfo* s) {
+ auto is_accessible_ftor = [this] (soinfo* si) {
+ // This is workaround for apps hacking into soinfo list.
+ // and inserting their own entries into it. (http://b/37191433)
+ if (!si->has_min_version(3)) {
+ DL_WARN("Warning: invalid soinfo version for \"%s\" (assuming inaccessible)",
+ si->get_soname());
+ return false;
+ }
+
+ if (si->get_primary_namespace() == this) {
+ return true;
+ }
+
+ const android_namespace_list_t& secondary_namespaces = si->get_secondary_namespaces();
+ if (secondary_namespaces.find(this) != secondary_namespaces.end()) {
+ return true;
+ }
+
+ return false;
+ };
+
+ if (is_accessible_ftor(s)) {
+ return true;
+ }
+
+ return !s->get_parents().visit([&](soinfo* si) {
+ return !is_accessible_ftor(si);
+ });
+}
+
+// TODO: this is slightly unusual way to construct
+// the global group for relocation. Not every RTLD_GLOBAL
+// library is included in this group for backwards-compatibility
+// reasons.
+//
+// This group consists of the main executable, LD_PRELOADs
+// and libraries with the DF_1_GLOBAL flag set.
+soinfo_list_t android_namespace_t::get_global_group() {
+ soinfo_list_t global_group;
+ soinfo_list().for_each([&](soinfo* si) {
+ if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+ global_group.push_back(si);
+ }
+ });
+
+ return global_group;
+}
+
+// This function provides a list of libraries to be shared
+// by the namespace. For the default namespace this is the global
+// group (see get_global_group). For all others this is a group
+// of RTLD_GLOBAL libraries (which includes the global group from
+// the default namespace).
+soinfo_list_t android_namespace_t::get_shared_group() {
+ if (this == g_default_namespace) {
+ return get_global_group();
+ }
+
+ soinfo_list_t shared_group;
+ soinfo_list().for_each([&](soinfo* si) {
+ if ((si->get_rtld_flags() & RTLD_GLOBAL) != 0) {
+ shared_group.push_back(si);
+ }
+ });
+
+ return shared_group;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_namespaces.h
^
|
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "linker_common_types.h"
+
+#include <string>
+#include <vector>
+#include <unordered_set>
+
+struct android_namespace_t;
+
+struct android_namespace_link_t {
+ public:
+ android_namespace_link_t(android_namespace_t* linked_namespace,
+ const std::unordered_set<std::string>& shared_lib_sonames,
+ bool allow_all_shared_libs)
+ : linked_namespace_(linked_namespace), shared_lib_sonames_(shared_lib_sonames),
+ allow_all_shared_libs_(allow_all_shared_libs)
+ {}
+
+ android_namespace_t* linked_namespace() const {
+ return linked_namespace_;
+ }
+
+ const std::unordered_set<std::string>& shared_lib_sonames() const {
+ return shared_lib_sonames_;
+ }
+
+ bool is_accessible(const char* soname) const {
+ if (soname == nullptr) {
+ return false;
+ }
+ return allow_all_shared_libs_ || shared_lib_sonames_.find(soname) != shared_lib_sonames_.end();
+ }
+
+ bool allow_all_shared_libs() const {
+ return allow_all_shared_libs_;
+ }
+
+ private:
+ android_namespace_t* const linked_namespace_;
+ const std::unordered_set<std::string> shared_lib_sonames_;
+ bool allow_all_shared_libs_;
+};
+
+struct android_namespace_t {
+ public:
+ android_namespace_t() : name_(nullptr), is_isolated_(false), is_greylist_enabled_(false) {}
+
+ const char* get_name() const { return name_; }
+ void set_name(const char* name) { name_ = name; }
+
+ bool is_isolated() const { return is_isolated_; }
+ void set_isolated(bool isolated) { is_isolated_ = isolated; }
+
+ bool is_greylist_enabled() const { return is_greylist_enabled_; }
+ void set_greylist_enabled(bool enabled) { is_greylist_enabled_ = enabled; }
+
+ const std::vector<std::string>& get_ld_library_paths() const {
+ return ld_library_paths_;
+ }
+ void set_ld_library_paths(std::vector<std::string>&& library_paths) {
+ ld_library_paths_ = std::move(library_paths);
+ }
+
+ const std::vector<std::string>& get_default_library_paths() const {
+ return default_library_paths_;
+ }
+ void set_default_library_paths(std::vector<std::string>&& library_paths) {
+ default_library_paths_ = std::move(library_paths);
+ }
+ void set_default_library_paths(const std::vector<std::string>& library_paths) {
+ default_library_paths_ = library_paths;
+ }
+
+ const std::vector<std::string>& get_permitted_paths() const {
+ return permitted_paths_;
+ }
+ void set_permitted_paths(std::vector<std::string>&& permitted_paths) {
+ permitted_paths_ = std::move(permitted_paths);
+ }
+ void set_permitted_paths(const std::vector<std::string>& permitted_paths) {
+ permitted_paths_ = permitted_paths;
+ }
+
+ const std::vector<std::string>& get_whitelisted_libs() const {
+ return whitelisted_libs_;
+ }
+ void set_whitelisted_libs(std::vector<std::string>&& whitelisted_libs) {
+ whitelisted_libs_ = std::move(whitelisted_libs);
+ }
+ void set_whitelisted_libs(const std::vector<std::string>& whitelisted_libs) {
+ whitelisted_libs_ = whitelisted_libs;
+ }
+
+ const std::vector<android_namespace_link_t>& linked_namespaces() const {
+ return linked_namespaces_;
+ }
+ void add_linked_namespace(android_namespace_t* linked_namespace,
+ const std::unordered_set<std::string>& shared_lib_sonames,
+ bool allow_all_shared_libs) {
+ linked_namespaces_.push_back(
+ android_namespace_link_t(linked_namespace, shared_lib_sonames, allow_all_shared_libs));
+ }
+
+ void add_soinfo(soinfo* si) {
+ soinfo_list_.push_back(si);
+ }
+
+ void add_soinfos(const soinfo_list_t& soinfos) {
+ for (auto si : soinfos) {
+ add_soinfo(si);
+ }
+ }
+
+ void remove_soinfo(soinfo* si) {
+ soinfo_list_.remove_if([&](soinfo* candidate) {
+ return si == candidate;
+ });
+ }
+
+ const soinfo_list_t& soinfo_list() const { return soinfo_list_; }
+
+ // For isolated namespaces - checks if the file is on the search path;
+ // always returns true for not isolated namespace.
+ bool is_accessible(const std::string& path);
+
+ // Returns true if si is accessible from this namespace. A soinfo
+ // is considered accessible when it belongs to this namespace
+ // or one of it's parent soinfos belongs to this namespace.
+ bool is_accessible(soinfo* si);
+
+ soinfo_list_t get_global_group();
+ soinfo_list_t get_shared_group();
+
+ private:
+ const char* name_;
+ bool is_isolated_;
+ bool is_greylist_enabled_;
+ std::vector<std::string> ld_library_paths_;
+ std::vector<std::string> default_library_paths_;
+ std::vector<std::string> permitted_paths_;
+ std::vector<std::string> whitelisted_libs_;
+ // Loader looks into linked namespace if it was not able
+ // to find a library in this namespace. Note that library
+ // lookup in linked namespaces are limited by the list of
+ // shared sonames.
+ std::vector<android_namespace_link_t> linked_namespaces_;
+ soinfo_list_t soinfo_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(android_namespace_t);
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_phdr.cpp
^
|
@@ -0,0 +1,1110 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hybris_compat.h"
+
+#include "linker_phdr.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+//#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "linker.h"
+#include "linker_dlwarning.h"
+#include "linker_globals.h"
+#include "linker_debug.h"
+#include "linker_utils.h"
+
+#include <android/api-level.h>
+
+#include "private/CFIShadow.h" // For kLibraryAlignment
+#include "private/bionic_prctl.h"
+
+static int GetTargetElfMachine() {
+#if defined(__arm__)
+ return EM_ARM;
+#elif defined(__aarch64__)
+ return EM_AARCH64;
+#elif defined(__i386__)
+ return EM_386;
+#elif defined(__mips__)
+ return EM_MIPS;
+#elif defined(__x86_64__)
+ return EM_X86_64;
+#endif
+}
+
+/**
+ TECHNICAL NOTE ON ELF LOADING.
+
+ An ELF file's program header table contains one or more PT_LOAD
+ segments, which corresponds to portions of the file that need to
+ be mapped into the process' address space.
+
+ Each loadable segment has the following important properties:
+
+ p_offset -> segment file offset
+ p_filesz -> segment file size
+ p_memsz -> segment memory size (always >= p_filesz)
+ p_vaddr -> segment's virtual address
+ p_flags -> segment flags (e.g. readable, writable, executable)
+
+ We will ignore the p_paddr and p_align fields of ElfW(Phdr) for now.
+
+ The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz)
+ ranges of virtual addresses. A few rules apply:
+
+ - the virtual address ranges should not overlap.
+
+ - if a segment's p_filesz is smaller than its p_memsz, the extra bytes
+ between them should always be initialized to 0.
+
+ - ranges do not necessarily start or end at page boundaries. Two distinct
+ segments can have their start and end on the same page. In this case, the
+ page inherits the mapping flags of the latter segment.
+
+ Finally, the real load addrs of each segment is not p_vaddr. Instead the
+ loader decides where to load the first segment, then will load all others
+ relative to the first one to respect the initial range layout.
+
+ For example, consider the following list:
+
+ [ offset:0, filesz:0x4000, memsz:0x4000, vaddr:0x30000 ],
+ [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ],
+
+ This corresponds to two segments that cover these virtual address ranges:
+
+ 0x30000...0x34000
+ 0x40000...0x48000
+
+ If the loader decides to load the first segment at address 0xa0000000
+ then the segments' load address ranges will be:
+
+ 0xa0030000...0xa0034000
+ 0xa0040000...0xa0048000
+
+ In other words, all segments must be loaded at an address that has the same
+ constant offset from their p_vaddr value. This offset is computed as the
+ difference between the first segment's load address, and its p_vaddr value.
+
+ However, in practice, segments do _not_ start at page boundaries. Since we
+ can only memory-map at page boundaries, this means that the bias is
+ computed as:
+
+ load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr)
+
+ (NOTE: The value must be used as a 32-bit unsigned integer, to deal with
+ possible wrap around UINT32_MAX for possible large p_vaddr values).
+
+ And that the phdr0_load_address must start at a page boundary, with
+ the segment's real content starting at:
+
+ phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr)
+
+ Note that ELF requires the following condition to make the mmap()-ing work:
+
+ PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset)
+
+ The load_bias must be added to any p_vaddr value read from the ELF file to
+ determine the corresponding memory address.
+
+ **/
+
+#define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0)
+#define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
+ MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
+ MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
+
+ElfReader::ElfReader()
+ : did_read_(false), did_load_(false), fd_(-1), file_offset_(0), file_size_(0), phdr_num_(0),
+ phdr_table_(nullptr), shdr_table_(nullptr), shdr_num_(0), dynamic_(nullptr), strtab_(nullptr),
+ strtab_size_(0), load_start_(nullptr), load_size_(0), load_bias_(0), loaded_phdr_(nullptr),
+ mapped_by_caller_(false) {
+}
+
+bool ElfReader::Read(const char* name, int fd, off64_t file_offset, off64_t file_size) {
+ if (did_read_) {
+ return true;
+ }
+ name_ = name;
+ fd_ = fd;
+ file_offset_ = file_offset;
+ file_size_ = file_size;
+
+ if (ReadElfHeader() &&
+ VerifyElfHeader() &&
+ ReadProgramHeaders() &&
+ ReadSectionHeaders() &&
+ ReadDynamicSection()) {
+ did_read_ = true;
+ }
+
+ return did_read_;
+}
+
+bool ElfReader::Load(address_space_params* address_space) {
+ CHECK(did_read_);
+ if (did_load_) {
+ return true;
+ }
+ if (ReserveAddressSpace(address_space) && LoadSegments() && FindPhdr()) {
+ did_load_ = true;
+ }
+
+ return did_load_;
+}
+
+const char* ElfReader::get_string(ElfW(Word) index) const {
+ CHECK(strtab_ != nullptr);
+ CHECK(index < strtab_size_);
+
+ return strtab_ + index;
+}
+
+bool ElfReader::ReadElfHeader() {
+ ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
+ if (rc < 0) {
+ DL_ERR("can't read file \"%s\": %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ if (rc != sizeof(header_)) {
+ DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
+ static_cast<size_t>(rc));
+ return false;
+ }
+ return true;
+}
+
+static const char* EM_to_string(int em) {
+ if (em == EM_386) return "EM_386";
+ if (em == EM_AARCH64) return "EM_AARCH64";
+ if (em == EM_ARM) return "EM_ARM";
+ if (em == EM_MIPS) return "EM_MIPS";
+ if (em == EM_X86_64) return "EM_X86_64";
+ return "EM_???";
+}
+
+bool ElfReader::VerifyElfHeader() {
+ if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
+ DL_ERR("\"%s\" has bad ELF magic: %02x%02x%02x%02x", name_.c_str(),
+ header_.e_ident[0], header_.e_ident[1], header_.e_ident[2], header_.e_ident[3]);
+ return false;
+ }
+
+ // Try to give a clear diagnostic for ELF class mismatches, since they're
+ // an easy mistake to make during the 32-bit/64-bit transition period.
+ int elf_class = header_.e_ident[EI_CLASS];
+#if defined(__LP64__)
+ if (elf_class != ELFCLASS64) {
+ if (elf_class == ELFCLASS32) {
+ DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_.c_str());
+ } else {
+ DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
+ }
+ return false;
+ }
+#else
+ if (elf_class != ELFCLASS32) {
+ if (elf_class == ELFCLASS64) {
+ DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_.c_str());
+ } else {
+ DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
+ }
+ return false;
+ }
+#endif
+
+ if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
+ DL_ERR("\"%s\" not little-endian: %d", name_.c_str(), header_.e_ident[EI_DATA]);
+ return false;
+ }
+
+ if (header_.e_type != ET_DYN) {
+ DL_ERR("\"%s\" has unexpected e_type: %d", name_.c_str(), header_.e_type);
+ return false;
+ }
+
+ if (header_.e_version != EV_CURRENT) {
+ DL_ERR("\"%s\" has unexpected e_version: %d", name_.c_str(), header_.e_version);
+ return false;
+ }
+
+ if (header_.e_machine != GetTargetElfMachine()) {
+ DL_ERR("\"%s\" is for %s (%d) instead of %s (%d)",
+ name_.c_str(),
+ EM_to_string(header_.e_machine), header_.e_machine,
+ EM_to_string(GetTargetElfMachine()), GetTargetElfMachine());
+ return false;
+ }
+
+ if (header_.e_shentsize != sizeof(ElfW(Shdr))) {
+ // Fail if app is targeting Android O or above
+ if (get_application_target_sdk_version() >= __ANDROID_API_O__) {
+ DL_ERR_AND_LOG("\"%s\" has unsupported e_shentsize: 0x%x (expected 0x%zx)",
+ name_.c_str(), header_.e_shentsize, sizeof(ElfW(Shdr)));
+ return false;
+ }
+ DL_WARN_documented_change(__ANDROID_API_O__,
+ "invalid-elf-header_section-headers-enforced-for-api-level-26",
+ "\"%s\" has unsupported e_shentsize 0x%x (expected 0x%zx)",
+ name_.c_str(), header_.e_shentsize, sizeof(ElfW(Shdr)));
+ add_dlwarning(name_.c_str(), "has invalid ELF header");
+ }
+
+ if (header_.e_shstrndx == 0) {
+ // Fail if app is targeting Android O or above
+ if (get_application_target_sdk_version() >= __ANDROID_API_O__) {
+ DL_ERR_AND_LOG("\"%s\" has invalid e_shstrndx", name_.c_str());
+ return false;
+ }
+
+ DL_WARN_documented_change(__ANDROID_API_O__,
+ "invalid-elf-header_section-headers-enforced-for-api-level-26",
+ "\"%s\" has invalid e_shstrndx", name_.c_str());
+ add_dlwarning(name_.c_str(), "has invalid ELF header");
+ }
+
+ return true;
+}
+
+bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment) {
+ off64_t range_start;
+ off64_t range_end;
+
+ // Only header can be located at the 0 offset... This function called to
+ // check DYNSYM and DYNAMIC sections and phdr/shdr - none of them can be
+ // at offset 0.
+
+ return offset > 0 &&
+ safe_add(&range_start, file_offset_, offset) &&
+ safe_add(&range_end, range_start, size) &&
+ (range_start < file_size_) &&
+ (range_end <= file_size_) &&
+ ((offset % alignment) == 0);
+}
+
+// Loads the program header table from an ELF file into a read-only private
+// anonymous mmap-ed block.
+bool ElfReader::ReadProgramHeaders() {
+ phdr_num_ = header_.e_phnum;
+
+ // Like the kernel, we only accept program header tables that
+ // are smaller than 64KiB.
+ if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
+ DL_ERR("\"%s\" has invalid e_phnum: %zd", name_.c_str(), phdr_num_);
+ return false;
+ }
+
+ // Boundary checks
+ size_t size = phdr_num_ * sizeof(ElfW(Phdr));
+ if (!CheckFileRange(header_.e_phoff, size, alignof(ElfW(Phdr)))) {
+ DL_ERR_AND_LOG("\"%s\" has invalid phdr offset/size: %zu/%zu",
+ name_.c_str(),
+ static_cast<size_t>(header_.e_phoff),
+ size);
+ return false;
+ }
+
+ if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
+ DL_ERR("\"%s\" phdr mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
+ return true;
+}
+
+bool ElfReader::ReadSectionHeaders() {
+ shdr_num_ = header_.e_shnum;
+
+ if (shdr_num_ == 0) {
+ DL_ERR_AND_LOG("\"%s\" has no section headers", name_.c_str());
+ return false;
+ }
+
+ size_t size = shdr_num_ * sizeof(ElfW(Shdr));
+ if (!CheckFileRange(header_.e_shoff, size, alignof(const ElfW(Shdr)))) {
+ DL_ERR_AND_LOG("\"%s\" has invalid shdr offset/size: %zu/%zu",
+ name_.c_str(),
+ static_cast<size_t>(header_.e_shoff),
+ size);
+ return false;
+ }
+
+ if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
+ DL_ERR("\"%s\" shdr mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_fragment_.data());
+ return true;
+}
+
+bool ElfReader::ReadDynamicSection() {
+ // 1. Find .dynamic section (in section headers)
+ const ElfW(Shdr)* dynamic_shdr = nullptr;
+ for (size_t i = 0; i < shdr_num_; ++i) {
+ if (shdr_table_[i].sh_type == SHT_DYNAMIC) {
+ dynamic_shdr = &shdr_table_ [i];
+ break;
+ }
+ }
+
+ if (dynamic_shdr == nullptr) {
+ DL_ERR_AND_LOG("\"%s\" .dynamic section header was not found", name_.c_str());
+ return false;
+ }
+
+ // Make sure dynamic_shdr offset and size matches PT_DYNAMIC phdr
+ size_t pt_dynamic_offset = 0;
+ size_t pt_dynamic_filesz = 0;
+ for (size_t i = 0; i < phdr_num_; ++i) {
+ const ElfW(Phdr)* phdr = &phdr_table_[i];
+ if (phdr->p_type == PT_DYNAMIC) {
+ pt_dynamic_offset = phdr->p_offset;
+ pt_dynamic_filesz = phdr->p_filesz;
+ }
+ }
+
+ if (pt_dynamic_offset != dynamic_shdr->sh_offset) {
+ if (get_application_target_sdk_version() >= __ANDROID_API_O__) {
+ DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid offset: 0x%zx, "
+ "expected to match PT_DYNAMIC offset: 0x%zx",
+ name_.c_str(),
+ static_cast<size_t>(dynamic_shdr->sh_offset),
+ pt_dynamic_offset);
+ return false;
+ }
+ DL_WARN_documented_change(__ANDROID_API_O__,
+ "invalid-elf-header_section-headers-enforced-for-api-level-26",
+ "\"%s\" .dynamic section has invalid offset: 0x%zx "
+ "(expected to match PT_DYNAMIC offset 0x%zx)",
+ name_.c_str(),
+ static_cast<size_t>(dynamic_shdr->sh_offset),
+ pt_dynamic_offset);
+ add_dlwarning(name_.c_str(), "invalid .dynamic section");
+ }
+
+ if (pt_dynamic_filesz != dynamic_shdr->sh_size) {
+ if (get_application_target_sdk_version() >= __ANDROID_API_O__) {
+ DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid size: 0x%zx, "
+ "expected to match PT_DYNAMIC filesz: 0x%zx",
+ name_.c_str(),
+ static_cast<size_t>(dynamic_shdr->sh_size),
+ pt_dynamic_filesz);
+ return false;
+ }
+ DL_WARN_documented_change(__ANDROID_API_O__,
+ "invalid-elf-header_section-headers-enforced-for-api-level-26",
+ "\"%s\" .dynamic section has invalid size: 0x%zx "
+ "(expected to match PT_DYNAMIC filesz 0x%zx)",
+ name_.c_str(),
+ static_cast<size_t>(dynamic_shdr->sh_size),
+ pt_dynamic_filesz);
+ add_dlwarning(name_.c_str(), "invalid .dynamic section");
+ }
+
+ if (dynamic_shdr->sh_link >= shdr_num_) {
+ DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid sh_link: %d",
+ name_.c_str(),
+ dynamic_shdr->sh_link);
+ return false;
+ }
+
+ const ElfW(Shdr)* strtab_shdr = &shdr_table_[dynamic_shdr->sh_link];
+
+ if (strtab_shdr->sh_type != SHT_STRTAB) {
+ DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid link(%d) sh_type: %d (expected SHT_STRTAB)",
+ name_.c_str(), dynamic_shdr->sh_link, strtab_shdr->sh_type);
+ return false;
+ }
+
+ if (!CheckFileRange(dynamic_shdr->sh_offset, dynamic_shdr->sh_size, alignof(const ElfW(Dyn)))) {
+ DL_ERR_AND_LOG("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
+ return false;
+ }
+
+ if (!dynamic_fragment_.Map(fd_, file_offset_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
+ DL_ERR("\"%s\" dynamic section mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_fragment_.data());
+
+ if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size, alignof(const char))) {
+ DL_ERR_AND_LOG("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
+ name_.c_str());
+ return false;
+ }
+
+ if (!strtab_fragment_.Map(fd_, file_offset_, strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
+ DL_ERR("\"%s\" strtab section mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ strtab_ = static_cast<const char*>(strtab_fragment_.data());
+ strtab_size_ = strtab_fragment_.size();
+ return true;
+}
+
+/* Returns the size of the extent of all the possibly non-contiguous
+ * loadable segments in an ELF program header table. This corresponds
+ * to the page-aligned size in bytes that needs to be reserved in the
+ * process' address space. If there are no loadable segments, 0 is
+ * returned.
+ *
+ * If out_min_vaddr or out_max_vaddr are not null, they will be
+ * set to the minimum and maximum addresses of pages to be reserved,
+ * or 0 if there is nothing to load.
+ */
+size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr)* out_min_vaddr,
+ ElfW(Addr)* out_max_vaddr) {
+ ElfW(Addr) min_vaddr = UINTPTR_MAX;
+ ElfW(Addr) max_vaddr = 0;
+
+ bool found_pt_load = false;
+ for (size_t i = 0; i < phdr_count; ++i) {
+ const ElfW(Phdr)* phdr = &phdr_table[i];
+
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+ found_pt_load = true;
+
+ if (phdr->p_vaddr < min_vaddr) {
+ min_vaddr = phdr->p_vaddr;
+ }
+
+ if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) {
+ max_vaddr = phdr->p_vaddr + phdr->p_memsz;
+ }
+ }
+ if (!found_pt_load) {
+ min_vaddr = 0;
+ }
+
+ min_vaddr = PAGE_START(min_vaddr);
+ max_vaddr = PAGE_END(max_vaddr);
+
+ if (out_min_vaddr != nullptr) {
+ *out_min_vaddr = min_vaddr;
+ }
+ if (out_max_vaddr != nullptr) {
+ *out_max_vaddr = max_vaddr;
+ }
+ return max_vaddr - min_vaddr;
+}
+
+// Reserve a virtual address range such that if it's limits were extended to the next 2**align
+// boundary, it would not overlap with any existing mappings.
+static void* ReserveAligned(size_t size, size_t align) {
+ int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
+ if (align == PAGE_SIZE) {
+ void* mmap_ptr = mmap(nullptr, size, PROT_NONE, mmap_flags, -1, 0);
+ if (mmap_ptr == MAP_FAILED) {
+ return nullptr;
+ }
+ return mmap_ptr;
+ }
+
+ // Allocate enough space so that the end of the desired region aligned up is still inside the
+ // mapping.
+ size_t mmap_size = align_up(size, align) + align - PAGE_SIZE;
+ uint8_t* mmap_ptr =
+ reinterpret_cast<uint8_t*>(mmap(nullptr, mmap_size, PROT_NONE, mmap_flags, -1, 0));
+ if (mmap_ptr == MAP_FAILED) {
+ return nullptr;
+ }
+
+ uint8_t* first = align_up(mmap_ptr, align);
+ uint8_t* last = align_down(mmap_ptr + mmap_size, align) - size;
+
+ // arc4random* is not available in first stage init because /dev/urandom hasn't yet been
+ // created. Don't randomize then.
+ size_t n = is_first_stage_init() ? 0 : rand() % ((last - first) / PAGE_SIZE + 1);
+ uint8_t* start = first + n * PAGE_SIZE;
+ munmap(mmap_ptr, start - mmap_ptr);
+ munmap(start + size, mmap_ptr + mmap_size - (start + size));
+ return start;
+}
+
+// Reserve a virtual address range big enough to hold all loadable
+// segments of a program header table. This is done by creating a
+// private anonymous mmap() with PROT_NONE.
+bool ElfReader::ReserveAddressSpace(address_space_params* address_space) {
+ ElfW(Addr) min_vaddr;
+ load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
+ if (load_size_ == 0) {
+ DL_ERR("\"%s\" has no loadable segments", name_.c_str());
+ return false;
+ }
+
+ uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
+ void* start;
+
+ if (load_size_ > address_space->reserved_size) {
+ if (address_space->must_use_address) {
+ DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
+ load_size_ - address_space->reserved_size, load_size_, name_.c_str());
+ return false;
+ }
+ start = ReserveAligned(load_size_, kLibraryAlignment);
+ if (start == nullptr) {
+ DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_.c_str());
+ return false;
+ }
+ } else {
+ start = address_space->start_addr;
+ mapped_by_caller_ = true;
+
+ // Update the reserved address space to subtract the space used by this library.
+ address_space->start_addr = reinterpret_cast<uint8_t*>(address_space->start_addr) + load_size_;
+ address_space->reserved_size -= load_size_;
+ }
+
+ load_start_ = start;
+ load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
+ return true;
+}
+
+bool ElfReader::LoadSegments() {
+ for (size_t i = 0; i < phdr_num_; ++i) {
+ const ElfW(Phdr)* phdr = &phdr_table_[i];
+
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+
+ // Segment addresses in memory.
+ ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
+ ElfW(Addr) seg_end = seg_start + phdr->p_memsz;
+
+ ElfW(Addr) seg_page_start = PAGE_START(seg_start);
+ ElfW(Addr) seg_page_end = PAGE_END(seg_end);
+
+ ElfW(Addr) seg_file_end = seg_start + phdr->p_filesz;
+
+ // File offsets.
+ ElfW(Addr) file_start = phdr->p_offset;
+ ElfW(Addr) file_end = file_start + phdr->p_filesz;
+
+ ElfW(Addr) file_page_start = PAGE_START(file_start);
+ ElfW(Addr) file_length = file_end - file_page_start;
+
+ if (file_size_ <= 0) {
+ DL_ERR("\"%s\" invalid file size: %" PRId64, name_.c_str(), file_size_);
+ return false;
+ }
+
+ if (file_end > static_cast<size_t>(file_size_)) {
+ DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
+ " p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
+ name_.c_str(), i, reinterpret_cast<void*>(phdr->p_offset),
+ reinterpret_cast<void*>(phdr->p_filesz),
+ reinterpret_cast<void*>(file_end), file_size_);
+ return false;
+ }
+
+ if (file_length != 0) {
+ int prot = PFLAGS_TO_PROT(phdr->p_flags);
+ if ((prot & (PROT_EXEC | PROT_WRITE)) == (PROT_EXEC | PROT_WRITE)) {
+ // W + E PT_LOAD segments are not allowed in O.
+ if (get_application_target_sdk_version() >= __ANDROID_API_O__) {
+ DL_ERR_AND_LOG("\"%s\": W+E load segments are not allowed", name_.c_str());
+ return false;
+ }
+ DL_WARN_documented_change(__ANDROID_API_O__,
+ "writable-and-executable-segments-enforced-for-api-level-26",
+ "\"%s\" has load segments that are both writable and executable",
+ name_.c_str());
+ add_dlwarning(name_.c_str(), "W+E load segments");
+ }
+
+ void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
+ file_length,
+ prot,
+ MAP_FIXED|MAP_PRIVATE,
+ fd_,
+ file_offset_ + file_page_start);
+ if (seg_addr == MAP_FAILED) {
+ DL_ERR("couldn't map \"%s\" segment %zd: %s", name_.c_str(), i, strerror(errno));
+ return false;
+ }
+ }
+
+ // if the segment is writable, and does not end on a page boundary,
+ // zero-fill it until the page limit.
+ if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
+ memset(reinterpret_cast<void*>(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
+ }
+
+ seg_file_end = PAGE_END(seg_file_end);
+
+ // seg_file_end is now the first page address after the file
+ // content. If seg_end is larger, we need to zero anything
+ // between them. This is done by using a private anonymous
+ // map for all extra pages.
+ if (seg_page_end > seg_file_end) {
+ size_t zeromap_size = seg_page_end - seg_file_end;
+ void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
+ zeromap_size,
+ PFLAGS_TO_PROT(phdr->p_flags),
+ MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
+ -1,
+ 0);
+ if (zeromap == MAP_FAILED) {
+ DL_ERR("couldn't zero fill \"%s\" gap: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, zeromap, zeromap_size, ".bss");
+ }
+ }
+ return true;
+}
+
+/* Used internally. Used to set the protection bits of all loaded segments
+ * with optional extra flags (i.e. really PROT_WRITE). Used by
+ * phdr_table_protect_segments and phdr_table_unprotect_segments.
+ */
+static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, int extra_prot_flags) {
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+
+ for (; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) {
+ continue;
+ }
+
+ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+
+ int prot = PFLAGS_TO_PROT(phdr->p_flags);
+ if ((extra_prot_flags & PROT_WRITE) != 0) {
+ // make sure we're never simultaneously writable / executable
+ prot &= ~PROT_EXEC;
+ }
+
+ int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
+ seg_page_end - seg_page_start,
+ prot | extra_prot_flags);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Restore the original protection modes for all loadable segments.
+ * You should only call this after phdr_table_unprotect_segments and
+ * applying all relocations.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
+ size_t phdr_count, ElfW(Addr) load_bias) {
+ return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
+}
+
+/* Change the protection of all loaded segments in memory to writable.
+ * This is useful before performing relocations. Once completed, you
+ * will have to call phdr_table_protect_segments to restore the original
+ * protection flags on all segments.
+ *
+ * Note that some writable segments can also have their content turned
+ * to read-only by calling phdr_table_protect_gnu_relro. This is no
+ * performed here.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table,
+ size_t phdr_count, ElfW(Addr) load_bias) {
+ return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
+}
+
+/* Used internally by phdr_table_protect_gnu_relro and
+ * phdr_table_unprotect_gnu_relro.
+ */
+static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, int prot_flags) {
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+
+ for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_GNU_RELRO) {
+ continue;
+ }
+
+ // Tricky: what happens when the relro segment does not start
+ // or end at page boundaries? We're going to be over-protective
+ // here and put every page touched by the segment as read-only.
+
+ // This seems to match Ian Lance Taylor's description of the
+ // feature at http://www.airs.com/blog/archives/189.
+
+ // Extract:
+ // Note that the current dynamic linker code will only work
+ // correctly if the PT_GNU_RELRO segment starts on a page
+ // boundary. This is because the dynamic linker rounds the
+ // p_vaddr field down to the previous page boundary. If
+ // there is anything on the page which should not be read-only,
+ // the program is likely to fail at runtime. So in effect the
+ // linker must only emit a PT_GNU_RELRO segment if it ensures
+ // that it starts on a page boundary.
+ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+
+ int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
+ seg_page_end - seg_page_start,
+ prot_flags);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Apply GNU relro protection if specified by the program header. This will
+ * turn some of the pages of a writable PT_LOAD segment to read-only, as
+ * specified by one or more PT_GNU_RELRO segments. This must be always
+ * performed after relocations.
+ *
+ * The areas typically covered are .got and .data.rel.ro, these are
+ * read-only from the program's POV, but contain absolute addresses
+ * that need to be relocated before use.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table,
+ size_t phdr_count, ElfW(Addr) load_bias) {
+ return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
+}
+
+/* Serialize the GNU relro segments to the given file descriptor. This can be
+ * performed after relocations to allow another process to later share the
+ * relocated segment, if it was loaded at the same address.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * fd -> writable file descriptor to use
+ * file_offset -> pointer to offset into file descriptor to use/update
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table,
+ size_t phdr_count,
+ ElfW(Addr) load_bias,
+ int fd,
+ size_t* file_offset) {
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+
+ for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_GNU_RELRO) {
+ continue;
+ }
+
+ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+ ssize_t size = seg_page_end - seg_page_start;
+
+ ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void*>(seg_page_start), size));
+ if (written != size) {
+ return -1;
+ }
+ void* map = mmap(reinterpret_cast<void*>(seg_page_start), size, PROT_READ,
+ MAP_PRIVATE|MAP_FIXED, fd, *file_offset);
+ if (map == MAP_FAILED) {
+ return -1;
+ }
+ *file_offset += size;
+ }
+ return 0;
+}
+
+/* Where possible, replace the GNU relro segments with mappings of the given
+ * file descriptor. This can be performed after relocations to allow a file
+ * previously created by phdr_table_serialize_gnu_relro in another process to
+ * replace the dirty relocated pages, saving memory, if it was loaded at the
+ * same address. We have to compare the data before we map over it, since some
+ * parts of the relro segment may not be identical due to other libraries in
+ * the process being loaded at different addresses.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * fd -> readable file descriptor to use
+ * file_offset -> pointer to offset into file descriptor to use/update
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table,
+ size_t phdr_count,
+ ElfW(Addr) load_bias,
+ int fd,
+ size_t* file_offset) {
+ // Map the file at a temporary location so we can compare its contents.
+ struct stat file_stat;
+ if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
+ return -1;
+ }
+ off_t file_size = file_stat.st_size;
+ void* temp_mapping = nullptr;
+ if (file_size > 0) {
+ temp_mapping = mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (temp_mapping == MAP_FAILED) {
+ return -1;
+ }
+ }
+
+ // Iterate over the relro segments and compare/remap the pages.
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+
+ for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_GNU_RELRO) {
+ continue;
+ }
+
+ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+
+ char* file_base = static_cast<char*>(temp_mapping) + *file_offset;
+ char* mem_base = reinterpret_cast<char*>(seg_page_start);
+ size_t match_offset = 0;
+ size_t size = seg_page_end - seg_page_start;
+
+ if (file_size - *file_offset < size) {
+ // File is too short to compare to this segment. The contents are likely
+ // different as well (it's probably for a different library version) so
+ // just don't bother checking.
+ break;
+ }
+
+ while (match_offset < size) {
+ // Skip over dissimilar pages.
+ while (match_offset < size &&
+ memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) {
+ match_offset += PAGE_SIZE;
+ }
+
+ // Count similar pages.
+ size_t mismatch_offset = match_offset;
+ while (mismatch_offset < size &&
+ memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) {
+ mismatch_offset += PAGE_SIZE;
+ }
+
+ // Map over similar pages.
+ if (mismatch_offset > match_offset) {
+ void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
+ PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, *file_offset + match_offset);
+ if (map == MAP_FAILED) {
+ munmap(temp_mapping, file_size);
+ return -1;
+ }
+ }
+
+ match_offset = mismatch_offset;
+ }
+
+ // Add to the base file offset in case there are multiple relro segments.
+ *file_offset += size;
+ }
+ munmap(temp_mapping, file_size);
+ return 0;
+}
+
+
+#if defined(__arm__)
+
+# ifndef PT_ARM_EXIDX
+# define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */
+# endif
+
+/* Return the address and size of the .ARM.exidx section in memory,
+ * if present.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * Output:
+ * arm_exidx -> address of table in memory (null on failure).
+ * arm_exidx_count -> number of items in table (0 on failure).
+ * Return:
+ * 0 on error, -1 on failure (_no_ error code in errno)
+ */
+int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias,
+ ElfW(Addr)** arm_exidx, size_t* arm_exidx_count) {
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+
+ for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_ARM_EXIDX) {
+ continue;
+ }
+
+ *arm_exidx = reinterpret_cast<ElfW(Addr)*>(load_bias + phdr->p_vaddr);
+ *arm_exidx_count = phdr->p_memsz / 8;
+ return 0;
+ }
+ *arm_exidx = nullptr;
+ *arm_exidx_count = 0;
+ return -1;
+}
+#endif
+
+/* Return the address and size of the ELF file's .dynamic section in memory,
+ * or null if missing.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * Output:
+ * dynamic -> address of table in memory (null on failure).
+ * dynamic_flags -> protection flags for section (unset on failure)
+ * Return:
+ * void
+ */
+void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
+ ElfW(Word)* dynamic_flags) {
+ *dynamic = nullptr;
+ for (size_t i = 0; i<phdr_count; ++i) {
+ const ElfW(Phdr)& phdr = phdr_table[i];
+ if (phdr.p_type == PT_DYNAMIC) {
+ *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr.p_vaddr);
+ if (dynamic_flags) {
+ *dynamic_flags = phdr.p_flags;
+ }
+ return;
+ }
+ }
+}
+
+/* Return the program interpreter string, or nullptr if missing.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * Return:
+ * pointer to the program interpreter string.
+ */
+const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias) {
+ for (size_t i = 0; i<phdr_count; ++i) {
+ const ElfW(Phdr)& phdr = phdr_table[i];
+ if (phdr.p_type == PT_INTERP) {
+ return reinterpret_cast<const char*>(load_bias + phdr.p_vaddr);
+ }
+ }
+ return nullptr;
+}
+
+// Sets loaded_phdr_ to the address of the program header table as it appears
+// in the loaded segments in memory. This is in contrast with phdr_table_,
+// which is temporary and will be released before the library is relocated.
+bool ElfReader::FindPhdr() {
+ const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
+
+ // If there is a PT_PHDR, use it directly.
+ for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
+ if (phdr->p_type == PT_PHDR) {
+ return CheckPhdr(load_bias_ + phdr->p_vaddr);
+ }
+ }
+
+ // Otherwise, check the first loadable segment. If its file offset
+ // is 0, it starts with the ELF header, and we can trivially find the
+ // loaded program header from it.
+ for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
+ if (phdr->p_type == PT_LOAD) {
+ if (phdr->p_offset == 0) {
+ ElfW(Addr) elf_addr = load_bias_ + phdr->p_vaddr;
+ const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
+ ElfW(Addr) offset = ehdr->e_phoff;
+ return CheckPhdr(reinterpret_cast<ElfW(Addr)>(ehdr) + offset);
+ }
+ break;
+ }
+ }
+
+ DL_ERR("can't find loaded phdr for \"%s\"", name_.c_str());
+ return false;
+}
+
+// Ensures that our program header is actually within a loadable
+// segment. This should help catch badly-formed ELF files that
+// would cause the linker to crash later when trying to access it.
+bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
+ const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
+ ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
+ for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+ ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
+ ElfW(Addr) seg_end = phdr->p_filesz + seg_start;
+ if (seg_start <= loaded && loaded_end <= seg_end) {
+ loaded_phdr_ = reinterpret_cast<const ElfW(Phdr)*>(loaded);
+ return true;
+ }
+ }
+ DL_ERR("\"%s\" loaded phdr %p not in loadable segment",
+ name_.c_str(), reinterpret_cast<void*>(loaded));
+ return false;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_phdr.h
^
|
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+/* Declarations related to the ELF program header table and segments.
+ *
+ * The design goal is to provide an API that is as close as possible
+ * to the ELF spec, and does not depend on linker-specific data
+ * structures (e.g. the exact layout of struct soinfo).
+ */
+
+#include "linker.h"
+#include "linker_mapped_file_fragment.h"
+
+class ElfReader {
+ public:
+ ElfReader();
+
+ bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
+ bool Load(address_space_params* address_space);
+
+ const char* name() const { return name_.c_str(); }
+ size_t phdr_count() const { return phdr_num_; }
+ ElfW(Addr) load_start() const { return reinterpret_cast<ElfW(Addr)>(load_start_); }
+ size_t load_size() const { return load_size_; }
+ ElfW(Addr) load_bias() const { return load_bias_; }
+ const ElfW(Phdr)* loaded_phdr() const { return loaded_phdr_; }
+ const ElfW(Dyn)* dynamic() const { return dynamic_; }
+ const char* get_string(ElfW(Word) index) const;
+ bool is_mapped_by_caller() const { return mapped_by_caller_; }
+ ElfW(Addr) entry_point() const { return header_.e_entry + load_bias_; }
+
+ private:
+ bool ReadElfHeader();
+ bool VerifyElfHeader();
+ bool ReadProgramHeaders();
+ bool ReadSectionHeaders();
+ bool ReadDynamicSection();
+ bool ReserveAddressSpace(address_space_params* address_space);
+ bool LoadSegments();
+ bool FindPhdr();
+ bool CheckPhdr(ElfW(Addr));
+ bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
+
+ bool did_read_;
+ bool did_load_;
+ std::string name_;
+ int fd_;
+ off64_t file_offset_;
+ off64_t file_size_;
+
+ ElfW(Ehdr) header_;
+ size_t phdr_num_;
+
+ MappedFileFragment phdr_fragment_;
+ const ElfW(Phdr)* phdr_table_;
+
+ MappedFileFragment shdr_fragment_;
+ const ElfW(Shdr)* shdr_table_;
+ size_t shdr_num_;
+
+ MappedFileFragment dynamic_fragment_;
+ const ElfW(Dyn)* dynamic_;
+
+ MappedFileFragment strtab_fragment_;
+ const char* strtab_;
+ size_t strtab_size_;
+
+ // First page of reserved address space.
+ void* load_start_;
+ // Size in bytes of reserved address space.
+ size_t load_size_;
+ // Load bias.
+ ElfW(Addr) load_bias_;
+
+ // Loaded phdr.
+ const ElfW(Phdr)* loaded_phdr_;
+
+ // Is map owned by the caller
+ bool mapped_by_caller_;
+};
+
+size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
+
+int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
+ size_t phdr_count, ElfW(Addr) load_bias);
+
+int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias);
+
+int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias);
+
+int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, int fd, size_t* file_offset);
+
+int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, int fd, size_t* file_offset);
+
+#if defined(__arm__)
+int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
+ ElfW(Addr)** arm_exidx, size_t* arm_exidix_count);
+#endif
+
+void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
+ ElfW(Word)* dynamic_flags);
+
+const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias);
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_reloc_iterators.h
^
|
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "linker.h"
+
+#include <string.h>
+
+const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1;
+const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2;
+const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4;
+const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8;
+
+class plain_reloc_iterator {
+#if defined(USE_RELA)
+ typedef ElfW(Rela) rel_t;
+#else
+ typedef ElfW(Rel) rel_t;
+#endif
+ public:
+ plain_reloc_iterator(rel_t* rel_array, size_t count)
+ : begin_(rel_array), end_(begin_ + count), current_(begin_) {}
+
+ bool has_next() {
+ return current_ < end_;
+ }
+
+ rel_t* next() {
+ return current_++;
+ }
+ private:
+ rel_t* const begin_;
+ rel_t* const end_;
+ rel_t* current_;
+
+ DISALLOW_COPY_AND_ASSIGN(plain_reloc_iterator);
+};
+
+template <typename decoder_t>
+class packed_reloc_iterator {
+#if defined(USE_RELA)
+ typedef ElfW(Rela) rel_t;
+#else
+ typedef ElfW(Rel) rel_t;
+#endif
+ public:
+ explicit packed_reloc_iterator(decoder_t&& decoder)
+ : decoder_(decoder) {
+ // initialize fields
+ memset(&reloc_, 0, sizeof(reloc_));
+ relocation_count_ = decoder_.pop_front();
+ reloc_.r_offset = decoder_.pop_front();
+ relocation_index_ = 0;
+ relocation_group_index_ = 0;
+ group_size_ = 0;
+ }
+
+ bool has_next() const {
+ return relocation_index_ < relocation_count_;
+ }
+
+ rel_t* next() {
+ if (relocation_group_index_ == group_size_) {
+ if (!read_group_fields()) {
+ // Iterator is inconsistent state; it should not be called again
+ // but in case it is let's make sure has_next() returns false.
+ relocation_index_ = relocation_count_ = 0;
+ return nullptr;
+ }
+ }
+
+ if (is_relocation_grouped_by_offset_delta()) {
+ reloc_.r_offset += group_r_offset_delta_;
+ } else {
+ reloc_.r_offset += decoder_.pop_front();
+ }
+
+ if (!is_relocation_grouped_by_info()) {
+ reloc_.r_info = decoder_.pop_front();
+ }
+
+#if defined(USE_RELA)
+ if (is_relocation_group_has_addend() &&
+ !is_relocation_grouped_by_addend()) {
+ reloc_.r_addend += decoder_.pop_front();
+ }
+#endif
+
+ relocation_index_++;
+ relocation_group_index_++;
+
+ return &reloc_;
+ }
+ private:
+ bool read_group_fields() {
+ group_size_ = decoder_.pop_front();
+ group_flags_ = decoder_.pop_front();
+
+ if (is_relocation_grouped_by_offset_delta()) {
+ group_r_offset_delta_ = decoder_.pop_front();
+ }
+
+ if (is_relocation_grouped_by_info()) {
+ reloc_.r_info = decoder_.pop_front();
+ }
+
+ if (is_relocation_group_has_addend() &&
+ is_relocation_grouped_by_addend()) {
+#if !defined(USE_RELA)
+ // This platform does not support rela, and yet we have it encoded in android_rel section.
+ DL_ERR("unexpected r_addend in android.rel section");
+ return false;
+#else
+ reloc_.r_addend += decoder_.pop_front();
+ } else if (!is_relocation_group_has_addend()) {
+ reloc_.r_addend = 0;
+#endif
+ }
+
+ relocation_group_index_ = 0;
+ return true;
+ }
+
+ bool is_relocation_grouped_by_info() {
+ return (group_flags_ & RELOCATION_GROUPED_BY_INFO_FLAG) != 0;
+ }
+
+ bool is_relocation_grouped_by_offset_delta() {
+ return (group_flags_ & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0;
+ }
+
+ bool is_relocation_grouped_by_addend() {
+ return (group_flags_ & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0;
+ }
+
+ bool is_relocation_group_has_addend() {
+ return (group_flags_ & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0;
+ }
+
+ decoder_t decoder_;
+ size_t relocation_count_;
+ size_t group_size_;
+ size_t group_flags_;
+ size_t group_r_offset_delta_;
+ size_t relocation_index_;
+ size_t relocation_group_index_;
+ rel_t reloc_;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_relocs.h
^
|
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <elf.h>
+
+#define R_GENERIC_NONE 0 // R_*_NONE is always 0
+
+#if defined (__aarch64__)
+
+#define R_GENERIC_JUMP_SLOT R_AARCH64_JUMP_SLOT
+#define R_GENERIC_GLOB_DAT R_AARCH64_GLOB_DAT
+#define R_GENERIC_RELATIVE R_AARCH64_RELATIVE
+#define R_GENERIC_IRELATIVE R_AARCH64_IRELATIVE
+#define R_GENERIC_TLS_DTPMOD R_AARCH64_TLS_DTPMOD64
+#define R_GENERIC_TLS_DTPREL R_AARCH64_TLS_DTPREL64
+#define R_GENERIC_TLS_TPREL R_AARCH64_TLS_TPREL64
+#define R_GENERIC_TLSDESC R_AARCH64_TLSDESC
+
+#elif defined (__arm__)
+
+#define R_GENERIC_JUMP_SLOT R_ARM_JUMP_SLOT
+#define R_GENERIC_GLOB_DAT R_ARM_GLOB_DAT
+#define R_GENERIC_RELATIVE R_ARM_RELATIVE
+#define R_GENERIC_IRELATIVE R_ARM_IRELATIVE
+#define R_GENERIC_TLS_DTPMOD R_ARM_TLS_DTPMOD32
+#define R_GENERIC_TLS_DTPREL R_ARM_TLS_DTPOFF32
+#define R_GENERIC_TLS_TPREL R_ARM_TLS_TPOFF32
+#define R_GENERIC_TLSDESC R_ARM_TLS_DESC
+
+#elif defined (__i386__)
+
+#define R_GENERIC_JUMP_SLOT R_386_JMP_SLOT
+#define R_GENERIC_GLOB_DAT R_386_GLOB_DAT
+#define R_GENERIC_RELATIVE R_386_RELATIVE
+#define R_GENERIC_IRELATIVE R_386_IRELATIVE
+#define R_GENERIC_TLS_DTPMOD R_386_TLS_DTPMOD32
+#define R_GENERIC_TLS_DTPREL R_386_TLS_DTPOFF32
+#define R_GENERIC_TLS_TPREL R_386_TLS_TPOFF
+#define R_GENERIC_TLSDESC R_386_TLS_DESC
+
+#elif defined (__x86_64__)
+
+#define R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT
+#define R_GENERIC_GLOB_DAT R_X86_64_GLOB_DAT
+#define R_GENERIC_RELATIVE R_X86_64_RELATIVE
+#define R_GENERIC_IRELATIVE R_X86_64_IRELATIVE
+#define R_GENERIC_TLS_DTPMOD R_X86_64_DTPMOD64
+#define R_GENERIC_TLS_DTPREL R_X86_64_DTPOFF64
+#define R_GENERIC_TLS_TPREL R_X86_64_TPOFF64
+#define R_GENERIC_TLSDESC R_X86_64_TLSDESC
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_sdk_versions.cpp
^
|
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker.h"
+#include <android/api-level.h>
+#include <atomic>
+
+static std::atomic<int> g_target_sdk_version(__ANDROID_API__);
+
+void set_application_target_sdk_version(int target) {
+ // translate current sdk_version to platform sdk_version
+ if (target == 0) {
+ target = __ANDROID_API__;
+ }
+ g_target_sdk_version = target;
+}
+
+int get_application_target_sdk_version() {
+ return g_target_sdk_version;
+}
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_sleb128.h
^
|
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <async_safe/log.h>
+
+#include "linker_debug.h"
+
+// Helper classes for decoding LEB128, used in packed relocation data.
+// http://en.wikipedia.org/wiki/LEB128
+
+class sleb128_decoder {
+ public:
+ sleb128_decoder(const uint8_t* buffer, size_t count)
+ : current_(buffer), end_(buffer+count) { }
+
+ size_t pop_front() {
+ size_t value = 0;
+ static const size_t size = CHAR_BIT * sizeof(value);
+
+ size_t shift = 0;
+ uint8_t byte;
+
+ do {
+ if (current_ >= end_) {
+ async_safe_fatal("sleb128_decoder ran out of bounds");
+ }
+ byte = *current_++;
+ value |= (static_cast<size_t>(byte & 127) << shift);
+ shift += 7;
+ } while (byte & 128);
+
+ if (shift < size && (byte & 64)) {
+ value |= -(static_cast<size_t>(1) << shift);
+ }
+
+ return value;
+ }
+
+ private:
+ const uint8_t* current_;
+ const uint8_t* const end_;
+};
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_sleb128_test.cpp
^
|
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <gtest/gtest.h>
+
+#include "linker_sleb128.h"
+
+TEST(linker_sleb128, smoke) {
+ std::vector<uint8_t> encoding;
+ // 624485
+ encoding.push_back(0xe5);
+ encoding.push_back(0x8e);
+ encoding.push_back(0x26);
+ // 0
+ encoding.push_back(0x00);
+ // 1
+ encoding.push_back(0x01);
+ // 63
+ encoding.push_back(0x3f);
+ // 64
+ encoding.push_back(0xc0);
+ encoding.push_back(0x00);
+ // -1
+ encoding.push_back(0x7f);
+ // -624485
+ encoding.push_back(0x9b);
+ encoding.push_back(0xf1);
+ encoding.push_back(0x59);
+ // 2147483647
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0x07);
+ // -2147483648
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x78);
+#if defined(__LP64__)
+ // 9223372036854775807
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0xff);
+ encoding.push_back(0x00);
+ // -9223372036854775808
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x80);
+ encoding.push_back(0x7f);
+#endif
+ sleb128_decoder decoder(&encoding[0], encoding.size());
+
+ EXPECT_EQ(624485U, decoder.pop_front());
+
+ EXPECT_EQ(0U, decoder.pop_front());
+ EXPECT_EQ(1U, decoder.pop_front());
+ EXPECT_EQ(63U, decoder.pop_front());
+ EXPECT_EQ(64U, decoder.pop_front());
+ EXPECT_EQ(static_cast<size_t>(-1), decoder.pop_front());
+ EXPECT_EQ(static_cast<size_t>(-624485), decoder.pop_front());
+ EXPECT_EQ(2147483647U, decoder.pop_front());
+ EXPECT_EQ(static_cast<size_t>(-2147483648), decoder.pop_front());
+#if defined(__LP64__)
+ EXPECT_EQ(9223372036854775807ULL, decoder.pop_front());
+ EXPECT_EQ(static_cast<uint64_t>(-9223372036854775807LL - 1), decoder.pop_front());
+#endif
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_soinfo.cpp
^
|
@@ -0,0 +1,847 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_soinfo.h"
+
+#include <dlfcn.h>
+#include <elf.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <android/api-level.h>
+
+#include <async_safe/log.h>
+
+#include "linker_debug.h"
+#include "linker_globals.h"
+#include "linker_logger.h"
+#include "linker_utils.h"
+
+#include "hybris_compat.h"
+
+#define ELF_ST_TYPE(x) ((x) & 0xf)
+
+// TODO(dimitry): These functions are currently located in linker.cpp - find a better place for it
+bool find_verdef_version_index(const soinfo* si, const version_info* vi, ElfW(Versym)* versym);
+ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr);
+int get_application_target_sdk_version();
+
+soinfo::soinfo(android_namespace_t* ns, const char* realpath,
+ const struct stat* file_stat, off64_t file_offset,
+ int rtld_flags) {
+// memset(this, 0, sizeof(*this));
+
+ if (realpath != nullptr) {
+ realpath_ = realpath;
+ }
+
+ flags_ = FLAG_NEW_SOINFO;
+ version_ = SOINFO_VERSION;
+
+ if (file_stat != nullptr) {
+ this->st_dev_ = file_stat->st_dev;
+ this->st_ino_ = file_stat->st_ino;
+ this->file_offset_ = file_offset;
+ }
+
+ this->rtld_flags_ = rtld_flags;
+ this->primary_namespace_ = ns;
+}
+
+soinfo::~soinfo() {
+ g_soinfo_handles_map.erase(handle_);
+}
+
+void soinfo::set_dt_runpath(const char* path) {
+ if (!has_min_version(3)) {
+ return;
+ }
+
+ std::vector<std::string> runpaths;
+
+ split_path(path, ":", &runpaths);
+
+ std::string origin = dirname(get_realpath());
+ // FIXME: add $PLATFORM.
+ std::vector<std::pair<std::string, std::string>> params = {
+ {"ORIGIN", origin},
+/*#if defined(LIB_PATH)
+ {"LIB", LIB_PATH},
+#else
+#error "LIB_PATH not defined"
+#endif*/
+ };
+ for (auto&& s : runpaths) {
+ format_string(&s, params);
+ }
+
+ resolve_paths(runpaths, &dt_runpath_);
+}
+
+const ElfW(Versym)* soinfo::get_versym(size_t n) const {
+ if (has_min_version(2) && versym_ != nullptr) {
+ return versym_ + n;
+ }
+
+ return nullptr;
+}
+
+ElfW(Addr) soinfo::get_verneed_ptr() const {
+ if (has_min_version(2)) {
+ return verneed_ptr_;
+ }
+
+ return 0;
+}
+
+size_t soinfo::get_verneed_cnt() const {
+ if (has_min_version(2)) {
+ return verneed_cnt_;
+ }
+
+ return 0;
+}
+
+ElfW(Addr) soinfo::get_verdef_ptr() const {
+ if (has_min_version(2)) {
+ return verdef_ptr_;
+ }
+
+ return 0;
+}
+
+size_t soinfo::get_verdef_cnt() const {
+ if (has_min_version(2)) {
+ return verdef_cnt_;
+ }
+
+ return 0;
+}
+
+bool soinfo::find_symbol_by_name(SymbolName& symbol_name,
+ const version_info* vi,
+ const ElfW(Sym)** symbol) const {
+ uint32_t symbol_index;
+ bool success =
+ is_gnu_hash() ?
+ gnu_lookup(symbol_name, vi, &symbol_index) :
+ elf_lookup(symbol_name, vi, &symbol_index);
+
+ if (success) {
+ *symbol = symbol_index == 0 ? nullptr : symtab_ + symbol_index;
+ }
+
+ return success;
+}
+
+static bool is_symbol_global_and_defined(const soinfo* si, const ElfW(Sym)* s) {
+ if (ELF_ST_BIND(s->st_info) == STB_GLOBAL ||
+ ELF_ST_BIND(s->st_info) == STB_WEAK) {
+ return s->st_shndx != SHN_UNDEF;
+ } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) {
+ DL_WARN("Warning: unexpected ST_BIND value: %d for \"%s\" in \"%s\" (ignoring)",
+ ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
+ }
+
+ return false;
+}
+
+static const ElfW(Versym) kVersymHiddenBit = 0x8000;
+
+static inline bool is_versym_hidden(const ElfW(Versym)* versym) {
+ // the symbol is hidden if bit 15 of versym is set.
+ return versym != nullptr && (*versym & kVersymHiddenBit) != 0;
+}
+
+static inline bool check_symbol_version(const ElfW(Versym) verneed,
+ const ElfW(Versym)* verdef) {
+ return verneed == kVersymNotNeeded ||
+ verdef == nullptr ||
+ verneed == (*verdef & ~kVersymHiddenBit);
+}
+
+bool soinfo::gnu_lookup(SymbolName& symbol_name,
+ const version_info* vi,
+ uint32_t* symbol_index) const {
+ uint32_t hash = symbol_name.gnu_hash();
+ uint32_t h2 = hash >> gnu_shift2_;
+
+ uint32_t bloom_mask_bits = sizeof(ElfW(Addr))*8;
+ uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_;
+ ElfW(Addr) bloom_word = gnu_bloom_filter_[word_num];
+
+ *symbol_index = 0;
+
+ TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+
+ // test against bloom filter
+ if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
+ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+
+ return true;
+ }
+
+ // bloom test says "probably yes"...
+ uint32_t n = gnu_bucket_[hash % gnu_nbucket_];
+
+ if (n == 0) {
+ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+
+ return true;
+ }
+
+ // lookup versym for the version definition in this library
+ // note the difference between "version is not requested" (vi == nullptr)
+ // and "version not found". In the first case verneed is kVersymNotNeeded
+ // which implies that the default version can be accepted; the second case results in
+ // verneed = 1 (kVersymGlobal) and implies that we should ignore versioned symbols
+ // for this library and consider only *global* ones.
+ ElfW(Versym) verneed = 0;
+ if (!find_verdef_version_index(this, vi, &verneed)) {
+ return false;
+ }
+
+ do {
+ ElfW(Sym)* s = symtab_ + n;
+ const ElfW(Versym)* verdef = get_versym(n);
+ // skip hidden versions when verneed == kVersymNotNeeded (0)
+ if (verneed == kVersymNotNeeded && is_versym_hidden(verdef)) {
+ continue;
+ }
+ if (((gnu_chain_[n] ^ hash) >> 1) == 0 &&
+ check_symbol_version(verneed, verdef) &&
+ strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
+ is_symbol_global_and_defined(this, s)) {
+ TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(s->st_value),
+ static_cast<size_t>(s->st_size));
+ *symbol_index = n;
+ return true;
+ }
+ } while ((gnu_chain_[n++] & 1) == 0);
+
+ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+
+ return true;
+}
+
+bool soinfo::elf_lookup(SymbolName& symbol_name,
+ const version_info* vi,
+ uint32_t* symbol_index) const {
+ uint32_t hash = symbol_name.elf_hash();
+
+ TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
+ symbol_name.get_name(), get_realpath(),
+ reinterpret_cast<void*>(base), hash, hash % nbucket_);
+
+ ElfW(Versym) verneed = 0;
+ if (!find_verdef_version_index(this, vi, &verneed)) {
+ return false;
+ }
+
+ for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
+ ElfW(Sym)* s = symtab_ + n;
+ const ElfW(Versym)* verdef = get_versym(n);
+
+ // skip hidden versions when verneed == 0
+ if (verneed == kVersymNotNeeded && is_versym_hidden(verdef)) {
+ continue;
+ }
+
+ if (check_symbol_version(verneed, verdef) &&
+ strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
+ is_symbol_global_and_defined(this, s)) {
+ TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
+ symbol_name.get_name(), get_realpath(),
+ reinterpret_cast<void*>(s->st_value),
+ static_cast<size_t>(s->st_size));
+ *symbol_index = n;
+ return true;
+ }
+ }
+
+ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
+ symbol_name.get_name(), get_realpath(),
+ reinterpret_cast<void*>(base), hash, hash % nbucket_);
+
+ *symbol_index = 0;
+ return true;
+}
+
+ElfW(Sym)* soinfo::find_symbol_by_address(const void* addr) {
+ return is_gnu_hash() ? gnu_addr_lookup(addr) : elf_addr_lookup(addr);
+}
+
+static bool symbol_matches_soaddr(const ElfW(Sym)* sym, ElfW(Addr) soaddr) {
+ // Skip TLS symbols. A TLS symbol's value is relative to the start of the TLS segment rather than
+ // to the start of the solib. The solib only reserves space for the initialized part of the TLS
+ // segment. (i.e. .tdata is followed by .tbss, and .tbss overlaps other sections.)
+ return sym->st_shndx != SHN_UNDEF &&
+ ELF_ST_TYPE(sym->st_info) != STT_TLS &&
+ soaddr >= sym->st_value &&
+ soaddr < sym->st_value + sym->st_size;
+}
+
+ElfW(Sym)* soinfo::gnu_addr_lookup(const void* addr) {
+ ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - load_bias;
+
+ for (size_t i = 0; i < gnu_nbucket_; ++i) {
+ uint32_t n = gnu_bucket_[i];
+
+ if (n == 0) {
+ continue;
+ }
+
+ do {
+ ElfW(Sym)* sym = symtab_ + n;
+ if (symbol_matches_soaddr(sym, soaddr)) {
+ return sym;
+ }
+ } while ((gnu_chain_[n++] & 1) == 0);
+ }
+
+ return nullptr;
+}
+
+ElfW(Sym)* soinfo::elf_addr_lookup(const void* addr) {
+ ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - load_bias;
+
+ // Search the library's symbol table for any defined symbol which
+ // contains this address.
+ for (size_t i = 0; i < nchain_; ++i) {
+ ElfW(Sym)* sym = symtab_ + i;
+ if (symbol_matches_soaddr(sym, soaddr)) {
+ return sym;
+ }
+ }
+
+ return nullptr;
+}
+
+static void call_function(const char* function_name __unused,
+ linker_ctor_function_t function,
+ const char* realpath __unused) {
+ if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
+ return;
+ }
+
+ TRACE("[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+ function(g_argc, g_argv, g_envp);
+ TRACE("[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+}
+
+static void call_function(const char* function_name __unused,
+ linker_dtor_function_t function,
+ const char* realpath __unused) {
+ if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
+ return;
+ }
+
+ TRACE("[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+ function();
+ TRACE("[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+}
+
+template <typename F>
+static void call_array(const char* array_name __unused,
+ F* functions,
+ size_t count,
+ bool reverse,
+ const char* realpath) {
+ if (functions == nullptr) {
+ return;
+ }
+
+ TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
+
+ int begin = reverse ? (count - 1) : 0;
+ int end = reverse ? -1 : count;
+ int step = reverse ? -1 : 1;
+
+ for (int i = begin; i != end; i += step) {
+ TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
+ call_function("function", functions[i], realpath);
+ }
+
+ TRACE("[ Done calling %s for '%s' ]", array_name, realpath);
+}
+
+void soinfo::call_pre_init_constructors() {
+ // DT_PREINIT_ARRAY functions are called before any other constructors for executables,
+ // but ignored in a shared library.
+ call_array("DT_PREINIT_ARRAY", preinit_array_, preinit_array_count_, false, get_realpath());
+}
+
+// Defined somewhere else in this linker.
+extern "C" void* android_dlsym(void* handle, const char* symbol);
+
+void (*bionic___system_properties_init)(void) = NULL;
+
+void soinfo::call_constructors() {
+ if (constructors_called) {
+ return;
+ }
+
+ if (soname_ != nullptr && strcmp(soname_, "libc.so") == 0) {
+ DEBUG("HYBRIS: =============> Skipping libc.so (but initializing properties)\n");
+ bionic___system_properties_init = (void(*)())android_dlsym(this, "__system_properties_init");
+ if (!bionic___system_properties_init) {
+ fprintf(stderr, "Could not initialize android system properties!\n");
+ abort();
+ }
+ bionic___system_properties_init();
+ constructors_called = true;
+ return;
+ }
+
+ // We set constructors_called before actually calling the constructors, otherwise it doesn't
+ // protect against recursive constructor calls. One simple example of constructor recursion
+ // is the libc debug malloc, which is implemented in libc_malloc_debug_leak.so:
+ // 1. The program depends on libc, so libc's constructor is called here.
+ // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so.
+ // 3. dlopen() calls the constructors on the newly created
+ // soinfo for libc_malloc_debug_leak.so.
+ // 4. The debug .so depends on libc, so CallConstructors is
+ // called again with the libc soinfo. If it doesn't trigger the early-
+ // out above, the libc constructor will be called again (recursively!).
+ constructors_called = true;
+
+ if (!is_main_executable() && preinit_array_ != nullptr) {
+ // The GNU dynamic linker silently ignores these, but we warn the developer.
+ PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
+ }
+
+ get_children().for_each([] (soinfo* si) {
+ si->call_constructors();
+ });
+
+ if (!is_linker()) {
+ bionic_trace_begin((std::string("calling constructors: ") + get_realpath()).c_str());
+ }
+
+ // DT_INIT should be called before DT_INIT_ARRAY if both are present.
+ call_function("DT_INIT", init_func_, get_realpath());
+ call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false, get_realpath());
+
+ if (!is_linker()) {
+ bionic_trace_end();
+ }
+}
+
+void soinfo::call_destructors() {
+ if (!constructors_called || (soname_ != nullptr && (strcmp(soname_, "libc.so") == 0))) {
+ return;
+ }
+
+ ScopedTrace trace((std::string("calling destructors: ") + get_realpath()).c_str());
+
+ // DT_FINI_ARRAY must be parsed in reverse order.
+ call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true, get_realpath());
+
+ // DT_FINI should be called after DT_FINI_ARRAY if both are present.
+ call_function("DT_FINI", fini_func_, get_realpath());
+}
+
+void soinfo::add_child(soinfo* child) {
+ if (has_min_version(0)) {
+ child->parents_.push_back(this);
+ this->children_.push_back(child);
+ }
+}
+
+void soinfo::remove_all_links() {
+ if (!has_min_version(0)) {
+ return;
+ }
+
+ // 1. Untie connected soinfos from 'this'.
+ children_.for_each([&] (soinfo* child) {
+ child->parents_.remove_if([&] (const soinfo* parent) {
+ return parent == this;
+ });
+ });
+
+ parents_.for_each([&] (soinfo* parent) {
+ parent->children_.remove_if([&] (const soinfo* child) {
+ return child == this;
+ });
+ });
+
+ // 2. Remove from the primary namespace
+ primary_namespace_->remove_soinfo(this);
+ primary_namespace_ = nullptr;
+
+ // 3. Remove from secondary namespaces
+ secondary_namespaces_.for_each([&](android_namespace_t* ns) {
+ ns->remove_soinfo(this);
+ });
+
+
+ // 4. Once everything untied - clear local lists.
+ parents_.clear();
+ children_.clear();
+ secondary_namespaces_.clear();
+}
+
+dev_t soinfo::get_st_dev() const {
+ if (has_min_version(0)) {
+ return st_dev_;
+ }
+
+ return 0;
+};
+
+ino_t soinfo::get_st_ino() const {
+ if (has_min_version(0)) {
+ return st_ino_;
+ }
+
+ return 0;
+}
+
+off64_t soinfo::get_file_offset() const {
+ if (has_min_version(1)) {
+ return file_offset_;
+ }
+
+ return 0;
+}
+
+uint32_t soinfo::get_rtld_flags() const {
+ if (has_min_version(1)) {
+ return rtld_flags_;
+ }
+
+ return 0;
+}
+
+uint32_t soinfo::get_dt_flags_1() const {
+ if (has_min_version(1)) {
+ return dt_flags_1_;
+ }
+
+ return 0;
+}
+
+void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
+ if (has_min_version(1)) {
+ if ((dt_flags_1 & DF_1_GLOBAL) != 0) {
+ rtld_flags_ |= RTLD_GLOBAL;
+ }
+
+ if ((dt_flags_1 & DF_1_NODELETE) != 0) {
+ rtld_flags_ |= RTLD_NODELETE;
+ }
+
+ dt_flags_1_ = dt_flags_1;
+ }
+}
+
+void soinfo::set_nodelete() {
+ rtld_flags_ |= RTLD_NODELETE;
+}
+
+const char* soinfo::get_realpath() const {
+#if defined(__work_around_b_24465209__)
+ if (has_min_version(2)) {
+ return realpath_.c_str();
+ } else {
+ return old_name_;
+ }
+#else
+ return realpath_.c_str();
+#endif
+}
+
+void soinfo::set_soname(const char* soname) {
+#if defined(__work_around_b_24465209__)
+ if (has_min_version(2)) {
+ soname_ = soname;
+ }
+ strlcpy(old_name_, soname_, sizeof(old_name_));
+#else
+ soname_ = soname;
+#endif
+}
+
+const char* soinfo::get_soname() const {
+#if defined(__work_around_b_24465209__)
+ if (has_min_version(2)) {
+ return soname_;
+ } else {
+ return old_name_;
+ }
+#else
+ return soname_;
+#endif
+}
+
+// This is a return on get_children()/get_parents() if
+// 'this->flags' does not have FLAG_NEW_SOINFO set.
+static soinfo_list_t g_empty_list;
+
+soinfo_list_t& soinfo::get_children() {
+ if (has_min_version(0)) {
+ return children_;
+ }
+
+ return g_empty_list;
+}
+
+const soinfo_list_t& soinfo::get_children() const {
+ if (has_min_version(0)) {
+ return children_;
+ }
+
+ return g_empty_list;
+}
+
+soinfo_list_t& soinfo::get_parents() {
+ if (has_min_version(0)) {
+ return parents_;
+ }
+
+ return g_empty_list;
+}
+
+static std::vector<std::string> g_empty_runpath;
+
+const std::vector<std::string>& soinfo::get_dt_runpath() const {
+ if (has_min_version(3)) {
+ return dt_runpath_;
+ }
+
+ return g_empty_runpath;
+}
+
+android_namespace_t* soinfo::get_primary_namespace() {
+ if (has_min_version(3)) {
+ return primary_namespace_;
+ }
+
+ return g_default_namespace;
+}
+
+void soinfo::add_secondary_namespace(android_namespace_t* secondary_ns) {
+ CHECK(has_min_version(3));
+ secondary_namespaces_.push_back(secondary_ns);
+}
+
+android_namespace_list_t& soinfo::get_secondary_namespaces() {
+ CHECK(has_min_version(3));
+ return secondary_namespaces_;
+}
+
+soinfo_tls* soinfo::get_tls() const {
+ return has_min_version(5) ? tls_.get() : nullptr;
+}
+
+ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
+ if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
+ return call_ifunc_resolver(s->st_value + load_bias);
+ }
+
+ return static_cast<ElfW(Addr)>(s->st_value + load_bias);
+}
+
+const char* soinfo::get_string(ElfW(Word) index) const {
+ if (has_min_version(1) && (index >= strtab_size_)) {
+ async_safe_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d",
+ get_realpath(), strtab_size_, index);
+ }
+
+ return strtab_ + index;
+}
+
+bool soinfo::is_gnu_hash() const {
+ return (flags_ & FLAG_GNU_HASH) != 0;
+}
+
+bool soinfo::can_unload() const {
+ return !is_linked() ||
+ (
+ (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0
+ );
+}
+
+bool soinfo::is_linked() const {
+ return (flags_ & FLAG_LINKED) != 0;
+}
+
+bool soinfo::is_image_linked() const {
+ return (flags_ & FLAG_IMAGE_LINKED) != 0;
+}
+
+bool soinfo::is_main_executable() const {
+ return (flags_ & FLAG_EXE) != 0;
+}
+
+bool soinfo::is_linker() const {
+ return (flags_ & FLAG_LINKER) != 0;
+}
+
+void soinfo::set_linked() {
+ flags_ |= FLAG_LINKED;
+}
+
+void soinfo::set_image_linked() {
+ flags_ |= FLAG_IMAGE_LINKED;
+}
+
+void soinfo::set_linker_flag() {
+ flags_ |= FLAG_LINKER;
+}
+
+void soinfo::set_main_executable() {
+ flags_ |= FLAG_EXE;
+}
+
+size_t soinfo::increment_ref_count() {
+ return ++local_group_root_->ref_count_;
+}
+
+size_t soinfo::decrement_ref_count() {
+ return --local_group_root_->ref_count_;
+}
+
+size_t soinfo::get_ref_count() const {
+ return local_group_root_->ref_count_;
+}
+
+soinfo* soinfo::get_local_group_root() const {
+ return local_group_root_;
+}
+
+void soinfo::set_mapped_by_caller(bool mapped_by_caller) {
+ if (mapped_by_caller) {
+ flags_ |= FLAG_MAPPED_BY_CALLER;
+ } else {
+ flags_ &= ~FLAG_MAPPED_BY_CALLER;
+ }
+}
+
+bool soinfo::is_mapped_by_caller() const {
+ return (flags_ & FLAG_MAPPED_BY_CALLER) != 0;
+}
+
+// This function returns api-level at the time of
+// dlopen/load. Note that libraries opened by system
+// will always have 'current' api level.
+int soinfo::get_target_sdk_version() const {
+ if (!has_min_version(2)) {
+ return __ANDROID_API__;
+ }
+
+ return local_group_root_->target_sdk_version_;
+}
+
+uintptr_t soinfo::get_handle() const {
+ CHECK(has_min_version(3));
+ CHECK(handle_ != 0);
+ return handle_;
+}
+
+void* soinfo::to_handle() {
+ if (get_application_target_sdk_version() < __ANDROID_API_N__ || !has_min_version(3)) {
+ return this;
+ }
+
+ return reinterpret_cast<void*>(get_handle());
+}
+
+void soinfo::generate_handle() {
+ CHECK(has_min_version(3));
+ CHECK(handle_ == 0); // Make sure this is the first call
+
+ // Make sure the handle is unique and does not collide
+ // with special values which are RTLD_DEFAULT and RTLD_NEXT.
+ do {
+ if (!is_first_stage_init()) {
+ handle_ = rand();
+ //arc4random_buf(&handle_, sizeof(handle_));
+ } else {
+ // arc4random* is not available in init because /dev/urandom hasn't yet been
+ // created. So, when running with init, use the monotonically increasing
+ // numbers as handles
+ handle_ += 2;
+ }
+ // the least significant bit for the handle is always 1
+ // making it easy to test the type of handle passed to
+ // dl* functions.
+ handle_ = handle_ | 1;
+ } while (handle_ == reinterpret_cast<uintptr_t>(RTLD_DEFAULT) ||
+ handle_ == reinterpret_cast<uintptr_t>(RTLD_NEXT) ||
+ g_soinfo_handles_map.find(handle_) != g_soinfo_handles_map.end());
+
+ g_soinfo_handles_map[handle_] = this;
+}
+
+// TODO(dimitry): Move SymbolName methods to a separate file.
+
+uint32_t calculate_elf_hash(const char* name) {
+ const uint8_t* name_bytes = reinterpret_cast<const uint8_t*>(name);
+ uint32_t h = 0, g;
+
+ while (*name_bytes) {
+ h = (h << 4) + *name_bytes++;
+ g = h & 0xf0000000;
+ h ^= g;
+ h ^= g >> 24;
+ }
+
+ return h;
+}
+
+uint32_t SymbolName::elf_hash() {
+ if (!has_elf_hash_) {
+ elf_hash_ = calculate_elf_hash(name_);
+ has_elf_hash_ = true;
+ }
+
+ return elf_hash_;
+}
+
+uint32_t SymbolName::gnu_hash() {
+ if (!has_gnu_hash_) {
+ uint32_t h = 5381;
+ const uint8_t* name = reinterpret_cast<const uint8_t*>(name_);
+ while (*name != 0) {
+ h += (h << 5) + *name++; // h*33 + c = h + h * 32 + c = h + h << 5 + c
+ }
+
+ gnu_hash_ = h;
+ has_gnu_hash_ = true;
+ }
+
+ return gnu_hash_;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_soinfo.h
^
|
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <link.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "private/bionic_elf_tls.h"
+#include "linker_namespaces.h"
+#include "linker_tls.h"
+
+#define FLAG_LINKED 0x00000001
+#define FLAG_EXE 0x00000004 // The main executable
+#define FLAG_LINKER 0x00000010 // The linker itself
+#define FLAG_GNU_HASH 0x00000040 // uses gnu hash
+#define FLAG_MAPPED_BY_CALLER 0x00000080 // the map is reserved by the caller
+ // and should not be unmapped
+#define FLAG_IMAGE_LINKED 0x00000100 // Is image linked - this is a guard on link_image.
+ // The difference between this flag and
+ // FLAG_LINKED is that FLAG_LINKED
+ // means is set when load_group is
+ // successfully loaded whereas this
+ // flag is set to avoid linking image
+ // when link_image called for the
+ // second time. This situation happens
+ // when load group is crossing
+ // namespace boundary twice and second
+ // local group depends on the same libraries.
+#define FLAG_RESERVED 0x00000200 // This flag was set when there is at least one
+ // outstanding thread_local dtor
+ // registered with this soinfo. In such
+ // a case the actual unload is
+ // postponed until the last thread_local
+ // destructor associated with this
+ // soinfo is executed and this flag is
+ // unset.
+#define FLAG_NEW_SOINFO 0x40000000 // new soinfo format
+
+#define SOINFO_VERSION 5
+
+typedef void (*linker_dtor_function_t)();
+typedef void (*linker_ctor_function_t)(int, char**, char**);
+
+class SymbolName {
+ public:
+ explicit SymbolName(const char* name)
+ : name_(name), has_elf_hash_(false), has_gnu_hash_(false),
+ elf_hash_(0), gnu_hash_(0) { }
+
+ const char* get_name() {
+ return name_;
+ }
+
+ uint32_t elf_hash();
+ uint32_t gnu_hash();
+
+ private:
+ const char* name_;
+ bool has_elf_hash_;
+ bool has_gnu_hash_;
+ uint32_t elf_hash_;
+ uint32_t gnu_hash_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolName);
+};
+
+struct version_info {
+ constexpr version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {}
+
+ uint32_t elf_hash;
+ const char* name;
+ const soinfo* target_si;
+};
+
+// TODO(dimitry): remove reference from soinfo member functions to this class.
+class VersionTracker;
+
+struct soinfo_tls {
+ TlsSegment segment;
+ size_t module_id = kTlsUninitializedModuleId;
+};
+
+#if defined(__work_around_b_24465209__)
+#define SOINFO_NAME_LEN 128
+#endif
+
+struct soinfo {
+#if defined(__work_around_b_24465209__)
+ private:
+ char old_name_[SOINFO_NAME_LEN];
+#endif
+ public:
+ const ElfW(Phdr)* phdr;
+ size_t phnum;
+#if defined(__work_around_b_24465209__)
+ ElfW(Addr) unused0; // DO NOT USE, maintained for compatibility.
+#endif
+ ElfW(Addr) base;
+ size_t size;
+
+#if defined(__work_around_b_24465209__)
+ uint32_t unused1; // DO NOT USE, maintained for compatibility.
+#endif
+
+ ElfW(Dyn)* dynamic;
+
+#if defined(__work_around_b_24465209__)
+ uint32_t unused2; // DO NOT USE, maintained for compatibility
+ uint32_t unused3; // DO NOT USE, maintained for compatibility
+#endif
+
+ soinfo* next;
+ private:
+ uint32_t flags_;
+
+ const char* strtab_;
+ ElfW(Sym)* symtab_;
+
+ size_t nbucket_;
+ size_t nchain_;
+ uint32_t* bucket_;
+ uint32_t* chain_;
+
+#if defined(__mips__) || !defined(__LP64__)
+ // This is only used by mips and mips64, but needs to be here for
+ // all 32-bit architectures to preserve binary compatibility.
+ ElfW(Addr)** plt_got_;
+#endif
+
+#if defined(USE_RELA)
+ ElfW(Rela)* plt_rela_;
+ size_t plt_rela_count_;
+
+ ElfW(Rela)* rela_;
+ size_t rela_count_;
+#else
+ ElfW(Rel)* plt_rel_;
+ size_t plt_rel_count_;
+
+ ElfW(Rel)* rel_;
+ size_t rel_count_;
+#endif
+
+ linker_ctor_function_t* preinit_array_;
+ size_t preinit_array_count_;
+
+ linker_ctor_function_t* init_array_;
+ size_t init_array_count_;
+ linker_dtor_function_t* fini_array_;
+ size_t fini_array_count_;
+
+ linker_ctor_function_t init_func_;
+ linker_dtor_function_t fini_func_;
+
+#if defined(__arm__)
+ public:
+ // ARM EABI section used for stack unwinding.
+ uint32_t* ARM_exidx;
+ size_t ARM_exidx_count;
+ private:
+#elif defined(__mips__)
+ uint32_t mips_symtabno_;
+ uint32_t mips_local_gotno_;
+ uint32_t mips_gotsym_;
+ bool mips_relocate_got(const VersionTracker& version_tracker,
+ const soinfo_list_t& global_group,
+ const soinfo_list_t& local_group);
+#if !defined(__LP64__)
+ bool mips_check_and_adjust_fp_modes();
+#endif
+#endif
+ size_t ref_count_;
+ public:
+ link_map link_map_head;
+
+ bool constructors_called;
+
+ // When you read a virtual address from the ELF file, add this
+ // value to get the corresponding address in the process' address space.
+ ElfW(Addr) load_bias;
+
+#if !defined(__LP64__)
+ bool has_text_relocations;
+#endif
+ bool has_DT_SYMBOLIC;
+
+ public:
+ soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,
+ off64_t file_offset, int rtld_flags);
+ ~soinfo();
+
+ void call_constructors();
+ void call_destructors();
+ void call_pre_init_constructors();
+ bool prelink_image();
+ bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
+ const android_dlextinfo* extinfo, size_t* relro_fd_offset);
+ bool protect_relro();
+
+ void add_child(soinfo* child);
+ void remove_all_links();
+
+ ino_t get_st_ino() const;
+ dev_t get_st_dev() const;
+ off64_t get_file_offset() const;
+
+ uint32_t get_rtld_flags() const;
+ uint32_t get_dt_flags_1() const;
+ void set_dt_flags_1(uint32_t dt_flags_1);
+
+ soinfo_list_t& get_children();
+ const soinfo_list_t& get_children() const;
+
+ soinfo_list_t& get_parents();
+
+ bool find_symbol_by_name(SymbolName& symbol_name,
+ const version_info* vi,
+ const ElfW(Sym)** symbol) const;
+
+ ElfW(Sym)* find_symbol_by_address(const void* addr);
+ ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const;
+
+ const char* get_string(ElfW(Word) index) const;
+ bool can_unload() const;
+ bool is_gnu_hash() const;
+
+ bool inline has_min_version(uint32_t min_version __unused) const {
+#if defined(__work_around_b_24465209__)
+ return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
+#else
+ return true;
+#endif
+ }
+
+ bool is_linked() const;
+ bool is_linker() const;
+ bool is_main_executable() const;
+
+ void set_linked();
+ void set_linker_flag();
+ void set_main_executable();
+ void set_nodelete();
+
+ size_t increment_ref_count();
+ size_t decrement_ref_count();
+ size_t get_ref_count() const;
+
+ soinfo* get_local_group_root() const;
+
+ void set_soname(const char* soname);
+ const char* get_soname() const;
+ const char* get_realpath() const;
+ const ElfW(Versym)* get_versym(size_t n) const;
+ ElfW(Addr) get_verneed_ptr() const;
+ size_t get_verneed_cnt() const;
+ ElfW(Addr) get_verdef_ptr() const;
+ size_t get_verdef_cnt() const;
+
+ int get_target_sdk_version() const;
+
+ void set_dt_runpath(const char *);
+ const std::vector<std::string>& get_dt_runpath() const;
+ android_namespace_t* get_primary_namespace();
+ void add_secondary_namespace(android_namespace_t* secondary_ns);
+ android_namespace_list_t& get_secondary_namespaces();
+
+ soinfo_tls* get_tls() const;
+
+ void set_mapped_by_caller(bool reserved_map);
+ bool is_mapped_by_caller() const;
+
+ uintptr_t get_handle() const;
+ void generate_handle();
+ void* to_handle();
+
+ private:
+ bool is_image_linked() const;
+ void set_image_linked();
+
+ bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
+ ElfW(Sym)* elf_addr_lookup(const void* addr);
+ bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
+ ElfW(Sym)* gnu_addr_lookup(const void* addr);
+
+ bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
+ const char* sym_name, const version_info** vi);
+
+ template<typename ElfRelIteratorT>
+ bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
+ const soinfo_list_t& global_group, const soinfo_list_t& local_group);
+ bool relocate_relr();
+ void apply_relr_reloc(ElfW(Addr) offset);
+
+ private:
+ // This part of the structure is only available
+ // when FLAG_NEW_SOINFO is set in this->flags.
+ uint32_t version_;
+
+ // version >= 0
+ dev_t st_dev_;
+ ino_t st_ino_;
+
+ // dependency graph
+ soinfo_list_t children_;
+ soinfo_list_t parents_;
+
+ // version >= 1
+ off64_t file_offset_;
+ uint32_t rtld_flags_;
+ uint32_t dt_flags_1_;
+ size_t strtab_size_;
+
+ // version >= 2
+
+ size_t gnu_nbucket_;
+ uint32_t* gnu_bucket_;
+ uint32_t* gnu_chain_;
+ uint32_t gnu_maskwords_;
+ uint32_t gnu_shift2_;
+ ElfW(Addr)* gnu_bloom_filter_;
+
+ soinfo* local_group_root_;
+
+ uint8_t* android_relocs_;
+ size_t android_relocs_size_;
+
+ const char* soname_;
+ std::string realpath_;
+
+ const ElfW(Versym)* versym_;
+
+ ElfW(Addr) verdef_ptr_;
+ size_t verdef_cnt_;
+
+ ElfW(Addr) verneed_ptr_;
+ size_t verneed_cnt_;
+
+ int target_sdk_version_;
+
+ // version >= 3
+ std::vector<std::string> dt_runpath_;
+ android_namespace_t* primary_namespace_;
+ android_namespace_list_t secondary_namespaces_;
+ uintptr_t handle_;
+
+ friend soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si);
+
+ // version >= 4
+ ElfW(Relr)* relr_;
+ size_t relr_count_;
+
+ // version >= 5
+ std::unique_ptr<soinfo_tls> tls_;
+ std::vector<TlsDynamicResolverArg> tlsdesc_args_;
+};
+
+// This function is used by dlvsym() to calculate hash of sym_ver
+uint32_t calculate_elf_hash(const char* name);
+
+const char* fix_dt_needed(const char* dt_needed, const char* sopath);
+
+template<typename F>
+void for_each_dt_needed(const soinfo* si, F action) {
+ for (const ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_NEEDED) {
+ action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath()));
+ }
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_test_globals.cpp
^
|
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// To enable logging
+int g_ld_debug_verbosity = 0;
+
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_tls.cpp
^
|
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_tls.h"
+
+#include <vector>
+
+#include <android/versioning.h>
+#include "async_safe/CHECK.h"
+#include "private/ScopedRWLock.h"
+#include "private/ScopedSignalBlocker.h"
+#include "private/bionic_defs.h"
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_globals.h"
+#include "private/linker_native_bridge.h"
+#include "linker_main.h"
+#include "linker_soinfo.h"
+#include <stdint.h>
+
+__LIBC_HIDDEN__ _Atomic(size_t) __libc_tls_generation_copy = {SIZE_MAX};
+
+static bool g_static_tls_finished;
+static std::vector<TlsModule> g_tls_modules;
+
+static size_t get_unused_module_index() {
+ for (size_t i = 0; i < g_tls_modules.size(); ++i) {
+ if (g_tls_modules[i].soinfo_ptr == nullptr) {
+ return i;
+ }
+ }
+ g_tls_modules.push_back({});
+ __libc_shared_globals()->tls_modules.module_count = g_tls_modules.size();
+ __libc_shared_globals()->tls_modules.module_table = g_tls_modules.data();
+ return g_tls_modules.size() - 1;
+}
+
+#if 0
+static void register_tls_module(soinfo* si, size_t static_offset) {
+ TlsModules& libc_modules = __libc_shared_globals()->tls_modules;
+
+ // The global TLS module table points at the std::vector of modules declared
+ // in this file, so acquire a write lock before modifying the std::vector.
+ ScopedSignalBlocker ssb;
+ ScopedWriteLock locker(&libc_modules.rwlock);
+
+ size_t module_idx = get_unused_module_index();
+
+ soinfo_tls* si_tls = si->get_tls();
+ si_tls->module_id = __tls_module_idx_to_id(module_idx);
+
+ const size_t new_generation = ++libc_modules.generation;
+ __libc_tls_generation_copy = new_generation;
+ if (libc_modules.generation_libc_so != nullptr) {
+ *libc_modules.generation_libc_so = new_generation;
+ }
+
+ g_tls_modules[module_idx] = {
+ .segment = si_tls->segment,
+ .static_offset = static_offset,
+ .first_generation = new_generation,
+ .soinfo_ptr = si,
+ };
+}
+#endif
+
+#if 0
+static void unregister_tls_module(soinfo* si) {
+ ScopedSignalBlocker ssb;
+ ScopedWriteLock locker(&__libc_shared_globals()->tls_modules.rwlock);
+
+ soinfo_tls* si_tls = si->get_tls();
+ TlsModule& mod = g_tls_modules[__tls_module_id_to_idx(si_tls->module_id)];
+ CHECK(mod.static_offset == SIZE_MAX);
+ CHECK(mod.soinfo_ptr == si);
+ mod = {};
+ si_tls->module_id = kTlsUninitializedModuleId;
+}
+#endif
+
+// The reference is valid until a TLS module is registered or unregistered.
+const TlsModule& get_tls_module(size_t module_id) {
+ size_t module_idx = __tls_module_id_to_idx(module_id);
+ CHECK(module_idx < g_tls_modules.size());
+ return g_tls_modules[module_idx];
+}
+
+extern "C" void __linker_reserve_bionic_tls_in_static_tls() {
+ //__libc_shared_globals()->static_tls_layout.reserve_bionic_tls();
+}
+
+void linker_setup_exe_static_tls(const char* progname) {
+ soinfo* somain = solist_get_somain();
+ StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
+ if (somain->get_tls() == nullptr) {
+ //layout.reserve_exe_segment_and_tcb(nullptr, progname);
+ } else {
+ //register_tls_module(somain, layout.reserve_exe_segment_and_tcb(&somain->get_tls()->segment, progname));
+ }
+
+ // The pthread key data is located at the very front of bionic_tls. As a
+ // temporary workaround, allocate bionic_tls just after the thread pointer so
+ // Golang can find its pthread key, as long as the executable's TLS segment is
+ // small enough. Specifically, Golang scans forward 384 words from the TP on
+ // ARM.
+ // - http://b/118381796
+ // - https://github.com/golang/go/issues/29674
+ __linker_reserve_bionic_tls_in_static_tls();
+}
+
+void linker_finalize_static_tls() {
+ g_static_tls_finished = true;
+ //__libc_shared_globals()->static_tls_layout.finish_layout();
+}
+
+void register_soinfo_tls(soinfo* si) {
+ soinfo_tls* si_tls = si->get_tls();
+ if (si_tls == nullptr || si_tls->module_id != kTlsUninitializedModuleId) {
+ return;
+ }
+ size_t static_offset = SIZE_MAX;
+ if (!g_static_tls_finished) {
+ StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
+ //static_offset = layout.reserve_solib_segment(si_tls->segment);
+ }
+ // register_tls_module(si, static_offset);
+}
+
+void unregister_soinfo_tls(soinfo* si) {
+ soinfo_tls* si_tls = si->get_tls();
+ if (si_tls == nullptr || si_tls->module_id == kTlsUninitializedModuleId) {
+ return;
+ }
+ // return unregister_tls_module(si);
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_tls.h
^
|
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+
+#include "private/bionic_elf_tls.h"
+
+struct TlsModule;
+struct soinfo;
+
+void linker_setup_exe_static_tls(const char* progname);
+void linker_finalize_static_tls();
+
+void register_soinfo_tls(soinfo* si);
+void unregister_soinfo_tls(soinfo* si);
+
+const TlsModule& get_tls_module(size_t module_id);
+
+typedef size_t TlsDescResolverFunc(size_t);
+
+struct TlsDescriptor {
+#if defined(__arm__)
+ size_t arg;
+ TlsDescResolverFunc* func;
+#else
+ TlsDescResolverFunc* func;
+ size_t arg;
+#endif
+};
+
+struct TlsDynamicResolverArg {
+ size_t generation;
+ TlsIndex index;
+};
+
+extern "C" size_t tlsdesc_resolver_static(size_t);
+extern "C" size_t tlsdesc_resolver_dynamic(size_t);
+extern "C" size_t tlsdesc_resolver_unresolved_weak(size_t);
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_utils.cpp
^
|
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_utils.h"
+
+#include "linker_debug.h"
+#include "linker_globals.h"
+
+//#include "android-base/strings.h"
+#include "android-base/file.h"
+#include <android-base/unique_fd.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <linux/limits.h>
+#include <fcntl.h>
+
+#include <sstream>
+
+#include "hybris_compat.h"
+
+std::string trim(const std::string& s) {
+ std::string result;
+
+ if (s.size() == 0) {
+ return result;
+ }
+
+ size_t start_index = 0;
+ size_t end_index = s.size() - 1;
+
+ // Skip initial whitespace.
+ while (start_index < s.size()) {
+ if (!isspace(s[start_index])) {
+ break;
+ }
+ start_index++;
+ }
+
+ // Skip terminating whitespace.
+ while (end_index >= start_index) {
+ if (!isspace(s[end_index])) {
+ break;
+ }
+ end_index--;
+ }
+
+ // All spaces, no beef.
+ if (end_index < start_index) {
+ return "";
+ }
+ // Start_index is the first non-space, end_index is the last one.
+ return s.substr(start_index, end_index - start_index + 1);
+}
+
+std::vector<std::string> split(const std::string &text, const std::string &sep) {
+ std::vector<std::string> tokens;
+ std::size_t start = 0, end = 0;
+ while ((end = text.find(sep, start)) != std::string::npos) {
+ tokens.push_back(text.substr(start, end - start));
+ start = end + 1;
+ }
+ tokens.push_back(text.substr(start));
+ return tokens;
+}
+
+std::string join(const std::vector<std::string>& things, char separator) {
+ if (things.empty()) {
+ return "";
+ }
+ std::ostringstream result;
+ result << *things.begin();
+ for (auto it = std::next(things.begin()); it != things.end(); ++it) {
+ result << separator << *it;
+ }
+ return result.str();
+}
+
+void format_string(std::string* str, const std::vector<std::pair<std::string, std::string>>& params) {
+ size_t pos = 0;
+ while (pos < str->size()) {
+ pos = str->find("$", pos);
+ if (pos == std::string::npos) break;
+ for (const auto& param : params) {
+ const std::string& token = param.first;
+ const std::string& replacement = param.second;
+ if (str->substr(pos + 1, token.size()) == token) {
+ str->replace(pos, token.size() + 1, replacement);
+ // -1 to compensate for the ++pos below.
+ pos += replacement.size() - 1;
+ break;
+ } else if (str->substr(pos + 1, token.size() + 2) == "{" + token + "}") {
+ str->replace(pos, token.size() + 3, replacement);
+ pos += replacement.size() - 1;
+ break;
+ }
+ }
+ // Skip $ in case it did not match any of the known substitutions.
+ ++pos;
+ }
+}
+
+std::string dirname(const char* path) {
+ const char* last_slash = strrchr(path, '/');
+
+ if (last_slash == path) {
+ return "/";
+ } else if (last_slash == nullptr) {
+ return ".";
+ } else {
+ return std::string(path, last_slash - path);
+ }
+}
+
+bool normalize_path(const char* path, std::string* normalized_path) {
+ // Input should be an absolute path
+ if (path[0] != '/') {
+ PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
+ return false;
+ }
+
+ const size_t len = strlen(path) + 1;
+ char buf[len];
+
+ const char* in_ptr = path;
+ char* out_ptr = buf;
+
+ while (*in_ptr != 0) {
+ if (*in_ptr == '/') {
+ char c1 = in_ptr[1];
+ if (c1 == '.') {
+ char c2 = in_ptr[2];
+ if (c2 == '/') {
+ in_ptr += 2;
+ continue;
+ } else if (c2 == '.' && (in_ptr[3] == '/' || in_ptr[3] == 0)) {
+ in_ptr += 3;
+ while (out_ptr > buf && *--out_ptr != '/') {
+ }
+ if (in_ptr[0] == 0) {
+ // retain '/' (or write the initial '/' for "/..")
+ *out_ptr++ = '/';
+ }
+ continue;
+ }
+ } else if (c1 == '/') {
+ ++in_ptr;
+ continue;
+ }
+ }
+ *out_ptr++ = *in_ptr++;
+ }
+
+ *out_ptr = 0;
+ *normalized_path = buf;
+ return true;
+}
+
+bool file_is_in_dir(const std::string& file, const std::string& dir) {
+ const char* needle = dir.c_str();
+ const char* haystack = file.c_str();
+ size_t needle_len = strlen(needle);
+
+ return strncmp(haystack, needle, needle_len) == 0 &&
+ haystack[needle_len] == '/' &&
+ strchr(haystack + needle_len + 1, '/') == nullptr;
+}
+
+bool file_is_under_dir(const std::string& file, const std::string& dir) {
+ const char* needle = dir.c_str();
+ const char* haystack = file.c_str();
+ size_t needle_len = strlen(needle);
+
+ return strncmp(haystack, needle, needle_len) == 0 &&
+ haystack[needle_len] == '/';
+}
+
+const char* const kZipFileSeparator = "!/";
+
+bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path) {
+ std::string normalized_path;
+ if (!normalize_path(input_path, &normalized_path)) {
+ return false;
+ }
+
+ const char* const path = normalized_path.c_str();
+ TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+
+ // Treat an '!/' separator inside a path as the separator between the name
+ // of the zip file on disk and the subdirectory to search within it.
+ // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
+ // "bar/bas/x.so" within "foo.zip".
+ const char* const separator = strstr(path, kZipFileSeparator);
+ if (separator == nullptr) {
+ return false;
+ }
+
+ char buf[512];
+ if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
+ PRINT("Warning: ignoring very long library path: %s", path);
+ return false;
+ }
+
+ buf[separator - path] = '\0';
+
+ *zip_path = buf;
+ *entry_path = &buf[separator - path + 2];
+
+ return true;
+}
+
+constexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1);
+
+off64_t page_start(off64_t offset) {
+ return offset & kPageMask;
+}
+
+bool safe_add(off64_t* out, off64_t a, size_t b) {
+ CHECK(a >= 0);
+ if (static_cast<uint64_t>(INT64_MAX - a) < b) {
+ return false;
+ }
+
+ *out = a + b;
+ return true;
+}
+
+size_t page_offset(off64_t offset) {
+ return static_cast<size_t>(offset & (PAGE_SIZE-1));
+}
+
+void split_path(const char* path, const char* delimiters,
+ std::vector<std::string>* paths) {
+ if (path != nullptr && path[0] != 0) {
+ *paths = split(path, delimiters);
+ }
+}
+
+void resolve_paths(std::vector<std::string>& paths,
+ std::vector<std::string>* resolved_paths) {
+ resolved_paths->clear();
+ for (const auto& path : paths) {
+ // skip empty paths
+ if (path.empty()) {
+ continue;
+ }
+
+ char resolved_path[PATH_MAX];
+ const char* original_path = path.c_str();
+ if (realpath(original_path, resolved_path) != nullptr) {
+ struct stat s;
+ if (stat(resolved_path, &s) == -1) {
+ DL_WARN("Warning: cannot stat file \"%s\": %s (ignoring)", resolved_path, strerror(errno));
+ continue;
+ }
+ if (!S_ISDIR(s.st_mode)) {
+ DL_WARN("Warning: \"%s\" is not a directory (ignoring)", resolved_path);
+ continue;
+ }
+ resolved_paths->push_back(resolved_path);
+ } else {
+ std::string normalized_path;
+ if (!normalize_path(original_path, &normalized_path)) {
+ DL_WARN("Warning: unable to normalize \"%s\" (ignoring)", original_path);
+ continue;
+ }
+
+ std::string zip_path;
+ std::string entry_path;
+ if (parse_zip_path(normalized_path.c_str(), &zip_path, &entry_path)) {
+ if (realpath(zip_path.c_str(), resolved_path) == nullptr) {
+ DL_WARN("Warning: unable to resolve \"%s\": %s (ignoring)",
+ zip_path.c_str(), strerror(errno));
+ continue;
+ }
+
+ resolved_paths->push_back(std::string(resolved_path) + kZipFileSeparator + entry_path);
+ } else {
+ struct stat s;
+ if (stat(normalized_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode)) {
+ // Path is not a zip path, but an existing directory. Then add it
+ // although we failed to resolve it. b/119656753
+ resolved_paths->push_back(normalized_path);
+ }
+ }
+ }
+ }
+}
+
+bool is_first_stage_init() {
+ static bool ret = (getpid() == 1 && access("/proc/self/exe", F_OK) == -1);
+ return ret;
+}
+void stringAppendV(std::string* dst, const char* format, va_list ap) {
+ // First try with a small fixed size buffer
+ char space[1024];
+
+ // It's possible for methods that use a va_list to invalidate
+ // the data in it upon use. The fix is to make a copy
+ // of the structure before using it and use that copy instead.
+ va_list backup_ap;
+ va_copy(backup_ap, ap);
+ int result = vsnprintf(space, sizeof(space), format, backup_ap);
+ va_end(backup_ap);
+
+ if (result < static_cast<int>(sizeof(space))) {
+ if (result >= 0) {
+ // Normal case -- everything fit.
+ dst->append(space, result);
+ return;
+ }
+
+ if (result < 0) {
+ // Just an error.
+ return;
+ }
+ }
+
+ // Increase the buffer size to the size requested by vsnprintf,
+ // plus one for the closing \0.
+ int length = result + 1;
+ char* buf = new char[length];
+
+ // Restore the va_list before we use it again
+ va_copy(backup_ap, ap);
+ result = vsnprintf(buf, length, format, backup_ap);
+ va_end(backup_ap);
+
+ if (result >= 0 && result < length) {
+ // It fit
+ dst->append(buf, result);
+ }
+ delete[] buf;
+}
+
+
+void stringAppendF(std::string* dst, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ stringAppendV(dst,format, ap);
+ va_end(ap);
+}
+
+std::string stringPrintf(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ std::string result;
+ stringAppendV(&result, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+bool readFdToString(int fd, std::string* content) {
+ content->clear();
+
+ // Although original we had small files in mind, this code gets used for
+ // very large files too, where the std::string growth heuristics might not
+ // be suitable. https://code.google.com/p/android/issues/detail?id=258500.
+ struct stat sb;
+ if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
+ content->reserve(sb.st_size);
+ }
+
+ char buf[BUFSIZ];
+ ssize_t n;
+ while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
+ content->append(buf, n);
+ }
+ return (n == 0) ? true : false;
+}
+
+bool readFileToString(const std::string& path, std::string* content, bool follow_symlinks) {
+ content->clear();
+
+ int flags = O_RDONLY | O_CLOEXEC | O_BINARY | (follow_symlinks ? 0 : O_NOFOLLOW);
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags)));
+ if (fd == -1) {
+ return false;
+ }
+ return readFdToString(fd, content);
+}
+
+bool startsWith(const std::string& s, const char* prefix) {
+ return strncmp(s.c_str(), prefix, strlen(prefix)) == 0;
+}
+
+static bool endsWith(const std::string& s, const char* suffix, bool case_sensitive) {
+ size_t suffix_length = strlen(suffix);
+ size_t string_length = s.size();
+ if (suffix_length > string_length) {
+ return false;
+ }
+ size_t offset = string_length - suffix_length;
+ return (case_sensitive ? strncmp : strncasecmp)(s.c_str() + offset, suffix, suffix_length) == 0;
+}
+
+bool endsWith(const std::string& s, const char* suffix) {
+ return endsWith(s, suffix, true);
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_utils.h
^
|
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+std::string trim(const std::string& s);
+std::vector<std::string> split(const std::string &text, const std::string &sep);
+std::string join(const std::vector<std::string>& things, char separator);
+
+extern const char* const kZipFileSeparator;
+
+void format_string(std::string* str, const std::vector<std::pair<std::string, std::string>>& params);
+
+bool file_is_in_dir(const std::string& file, const std::string& dir);
+bool file_is_under_dir(const std::string& file, const std::string& dir);
+bool normalize_path(const char* path, std::string* normalized_path);
+bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path);
+
+// For every path element this function checks of it exists, and is a directory,
+// and normalizes it:
+// 1. For regular path it converts it to realpath()
+// 2. For path in a zip file it uses realpath on the zipfile
+// normalizes entry name by calling normalize_path function.
+void resolve_paths(std::vector<std::string>& paths,
+ std::vector<std::string>* resolved_paths);
+
+void split_path(const char* path, const char* delimiters, std::vector<std::string>* paths);
+
+std::string dirname(const char* path);
+
+off64_t page_start(off64_t offset);
+size_t page_offset(off64_t offset);
+bool safe_add(off64_t* out, off64_t a, size_t b);
+bool is_first_stage_init();
+
+void stringAppendV(std::string* dst, const char* format, va_list ap);
+void stringAppendF(std::string* dst, const char* format, ...);
+std::string stringPrintf(const char* fmt, ...);
+bool startsWith(const std::string& s, const char* prefix);
+bool endsWith(const std::string& s, const char* suffix);
+bool readFileToString(const std::string& path, std::string* content, bool follow_symlinks = false);
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_utils_test.cpp
^
|
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <gtest/gtest.h>
+
+#include "linker_utils.h"
+
+TEST(linker_utils, format_string) {
+ std::vector<std::pair<std::string, std::string>> params = {{ "LIB", "lib32"}, { "SDKVER", "42"}};
+ std::string str_smoke = "LIB$LIB${LIB${SDKVER}SDKVER$TEST$";
+ format_string(&str_smoke, params);
+ ASSERT_EQ("LIBlib32${LIB42SDKVER$TEST$", str_smoke);
+}
+
+TEST(linker_utils, normalize_path_smoke) {
+ std::string output;
+ ASSERT_TRUE(normalize_path("/../root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));
+ ASSERT_EQ("/root/dir/dir2/zipfile!/dir/afile", output);
+
+ ASSERT_TRUE(normalize_path("/../root///dir/.///dir2/somedir/.../zipfile!/.dir/dir9//..///afile", &output));
+ ASSERT_EQ("/root/dir/dir2/somedir/.../zipfile!/.dir/afile", output);
+
+ ASSERT_TRUE(normalize_path("/root/..", &output));
+ ASSERT_EQ("/", output);
+
+ ASSERT_TRUE(normalize_path("/root/notroot/..", &output));
+ ASSERT_EQ("/root/", output);
+
+ ASSERT_TRUE(normalize_path("/a/../../b", &output));
+ ASSERT_EQ("/b", output);
+
+ ASSERT_TRUE(normalize_path("/..", &output));
+ ASSERT_EQ("/", output);
+
+ output = "unchanged";
+ ASSERT_FALSE(normalize_path("root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));
+ ASSERT_EQ("unchanged", output);
+}
+
+TEST(linker_utils, file_is_in_dir_smoke) {
+ ASSERT_TRUE(file_is_in_dir("/foo/bar/file", "/foo/bar"));
+ ASSERT_FALSE(file_is_in_dir("/foo/bar/file", "/foo"));
+
+ ASSERT_FALSE(file_is_in_dir("/foo/bar/file", "/bar/foo"));
+
+ ASSERT_TRUE(file_is_in_dir("/file", ""));
+ ASSERT_FALSE(file_is_in_dir("/file", "/"));
+}
+
+TEST(linker_utils, file_is_under_dir_smoke) {
+ ASSERT_TRUE(file_is_under_dir("/foo/bar/file", "/foo/bar"));
+ ASSERT_TRUE(file_is_under_dir("/foo/bar/file", "/foo"));
+
+ ASSERT_FALSE(file_is_under_dir("/foo/bar/file", "/bar/foo"));
+
+ ASSERT_TRUE(file_is_under_dir("/file", ""));
+ ASSERT_TRUE(file_is_under_dir("/foo/bar/file", ""));
+ ASSERT_FALSE(file_is_under_dir("/file", "/"));
+ ASSERT_FALSE(file_is_under_dir("/foo/bar/file", "/"));
+}
+
+TEST(linker_utils, parse_zip_path_smoke) {
+ std::string zip_path;
+ std::string entry_path;
+
+ ASSERT_FALSE(parse_zip_path("/not/a/zip/path/file.zip", &zip_path, &entry_path));
+ ASSERT_FALSE(parse_zip_path("/not/a/zip/path/file.zip!path/in/zip", &zip_path, &entry_path));
+ ASSERT_TRUE(parse_zip_path("/zip/path/file.zip!/path/in/zip", &zip_path, &entry_path));
+ ASSERT_EQ("/zip/path/file.zip", zip_path);
+ ASSERT_EQ("path/in/zip", entry_path);
+
+ ASSERT_TRUE(parse_zip_path("/zip/path/file2.zip!/", &zip_path, &entry_path));
+ ASSERT_EQ("/zip/path/file2.zip", zip_path);
+ ASSERT_EQ("", entry_path);
+}
+
+TEST(linker_utils, page_start) {
+ ASSERT_EQ(0x0001000, page_start(0x0001000));
+ ASSERT_EQ(0x3002000, page_start(0x300222f));
+ ASSERT_EQ(0x6001000, page_start(0x6001fff));
+}
+
+TEST(linker_utils, page_offset) {
+ ASSERT_EQ(0x0U, page_offset(0x0001000));
+ ASSERT_EQ(0x22fU, page_offset(0x300222f));
+ ASSERT_EQ(0xfffU, page_offset(0x6001fff));
+}
+
+TEST(linker_utils, safe_add) {
+ int64_t val = 42;
+ ASSERT_FALSE(safe_add(&val, INT64_MAX-20, 21U));
+ ASSERT_EQ(42, val);
+ ASSERT_TRUE(safe_add(&val, INT64_MAX-42, 42U));
+ ASSERT_EQ(INT64_MAX, val);
+ ASSERT_TRUE(safe_add(&val, 2000, 42U));
+ ASSERT_EQ(2042, val);
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/linker_wrapper.cpp
^
|
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "private/KernelArgumentBlock.h"
+
+extern const char linker_offset;
+
+// This will be replaced by host_bionic_inject, but must be non-zero
+// here so that it's placed in the data section.
+uintptr_t original_start = 42;
+
+/* Find the load bias and base address of an executable or shared object loaded
+ * by the kernel. The ELF file's PHDR table must have a PT_PHDR entry.
+ *
+ * A VDSO doesn't have a PT_PHDR entry in its PHDR table.
+ */
+static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr)* base, ElfW(Addr)* load_bias) {
+ for (size_t i = 0; i < phdr_count; ++i) {
+ if (phdr_table[i].p_type == PT_PHDR) {
+ *load_bias = reinterpret_cast<ElfW(Addr)>(phdr_table) - phdr_table[i].p_vaddr;
+ *base = reinterpret_cast<ElfW(Addr)>(phdr_table) - phdr_table[i].p_offset;
+ return;
+ }
+ }
+}
+
+/*
+ * This is the entry point for the linker wrapper, which finds
+ * the real linker, then bootstraps into it.
+ */
+extern "C" ElfW(Addr) __linker_init(void* raw_args) {
+ KernelArgumentBlock args(raw_args);
+
+ ElfW(Addr) base_addr = 0;
+ ElfW(Addr) load_bias = 0;
+ get_elf_base_from_phdr(
+ reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR)), args.getauxval(AT_PHNUM),
+ &base_addr, &load_bias);
+
+ ElfW(Addr) linker_addr = base_addr + reinterpret_cast<uintptr_t>(&linker_offset);
+ ElfW(Addr) linker_entry_offset = reinterpret_cast<ElfW(Ehdr)*>(linker_addr)->e_entry;
+
+ for (ElfW(auxv_t)* v = args.auxv; v->a_type != AT_NULL; ++v) {
+ if (v->a_type == AT_BASE) {
+ // Set AT_BASE to the embedded linker
+ v->a_un.a_val = linker_addr;
+ }
+ if (v->a_type == AT_ENTRY) {
+ // Set AT_ENTRY to the proper entry point
+ v->a_un.a_val = base_addr + original_start;
+ }
+ }
+
+ // Return address of linker entry point
+ return linker_addr + linker_entry_offset;
+}
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/make.txt
^
|
@@ -0,0 +1,2 @@
+ CXX q_la-dlfcn.lo
+Makefile:612: recipe for target 'q_la-dlfcn.lo' failed
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/q/rt.cpp
^
|
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This function is an empty stub where GDB locates a breakpoint to get notified
+ * about linker activity. It canʼt be inlined away, can't be hidden.
+ */
+extern "C" void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity() {
+}
+
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/wrapper_code.h
^
|
@@ -22,7 +22,13 @@
extern "C" {
#endif
+#ifdef __aarch64__
void wrapper_code_generic() __attribute__((naked,noinline));
+#endif
+#ifdef __arm__
+void wrapper_code_generic() __attribute__((naked,noinline)) __attribute__((target("arm")));
+void wrapper_code_generic_thumb() __attribute__((naked,noinline)) __attribute__((target("thumb")));
+#endif
#ifdef __cplusplus
}
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/wrapper_code_generic_arm.c
^
|
@@ -20,27 +20,28 @@
void
wrapper_code_generic()
{
+#ifdef __arm__
// we can never use r0-r11, neither the stack
asm volatile(
// preserve the registers
- ".arm\n\
+ ".arm\n\
push {r0-r11, lr}\n"
- ".arm\n\
+ ".arm\n\
ldr r0, fun\n" // load the function pointer to r0
- ".arm\n\
+ ".arm\n\
ldr r1, name\n" // load the address of the functions name to r1
- ".arm\n\
+ ".arm\n\
ldr r2, str\n" // load the string to print
- ".arm\n\
+ ".arm\n\
ldr r4, tc\n" // load the address of trace_callback to r4
- ".arm\n\
+ ".arm\n\
blx r4\n" // call trace_callback
// restore the registers
- ".arm\n\
+ ".arm\n\
pop {r0-r11, lr}\n"
- ".arm\n\
+ ".arm\n\
ldr pc, fun\n" // jump to function
// dummy instructions, this is where we locate our pointers
@@ -49,4 +50,119 @@
"tc: .word 0xFFFFFFFF\n" // address of trace_callback
"str: .word 0xFFFFFFFF\n" // the string being printed in trace_callback
);
+#elif defined(__aarch64__)
+ // we can never use r0-r11, neither the stack
+ asm volatile(
+ // preserve the registers
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x0, x1, [sp]\n" // save 2 pairs of registers
+ "stp x2, x3, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x4, x5, [sp]\n" // save 2 pairs of registers
+ "stp x6, x7, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x8, x9, [sp]\n" // save 2 pairs of registers
+ "stp x10, x11, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x12, x13, [sp]\n" // save 2 pairs of registers
+ "stp x14, x15, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x16, x17, [sp]\n" // save 2 pairs of registers
+ "stp x18, x19, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x20, x21, [sp]\n" // save 2 pairs of registers
+ "stp x22, x23, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x24, x25, [sp]\n" // save 2 pairs of registers
+ "stp x26, x27, [sp,#16]\n"
+
+ "sub sp, sp, #32\n" // open up some temp stack space
+ "stp x28, x29, [sp]\n" // save a pair of registers
+ "str x30, [sp,#16]\n" // save x30
+
+ "ldr x0, fun\n" // load the function pointer to r0
+ "ldr x1, name\n" // load the address of the functions name to r1
+ "ldr x2, str\n" // load the string to print
+ "ldr x4, tc\n" // load the address of trace_callback to r4
+ "blr x4\n" // call trace_callback
+
+ // restore the registers
+ "ldp x28, x29, [sp]\n" // restore a pair of registers
+ "ldr x30, [sp,#16]\n" // restore x30
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x24, x25, [sp]\n" // restore 2 pairs of registers
+ "ldp x26, x27, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x20, x21, [sp]\n" // restore 2 pairs of registers
+ "ldp x22, x23, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x16, x17, [sp]\n" // restore 2 pairs of registers
+ "ldp x18, x19, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x12, x13, [sp]\n" // restore 2 pairs of registers
+ "ldp x14, x15, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x8, x9, [sp]\n" // restore 2 pairs of registers
+ "ldp x10, x11, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x4, x5, [sp]\n" // restore 2 pairs of registers
+ "ldp x6, x7, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldp x0, x1, [sp]\n" // restore 2 pairs of registers
+ "ldp x2, x3, [sp,#16]\n"
+ "add sp, sp, #32\n" // "free" the temp stack space
+
+ "ldr x15, fun\n" // load the function pointer to "temporary" r15
+ "br x15\n" // branch unconditionally to r15
+
+ // dummy instructions, this is where we locate our pointers
+ ".align 3\n" // advance location counter to be multiple of 8
+ "name: .dword 0xFFFFFFFFFFFFFFFF\n" // name of function to call
+ "fun: .dword 0xFFFFFFFFFFFFFFFF\n" // function to call
+ "tc: .dword 0xFFFFFFFFFFFFFFFF\n" // address of trace_callback
+ "str: .dword 0xFFFFFFFFFFFFFFFF\n" // the string being printed in trace_callback
+ );
+#endif
}
+
+#ifdef __arm__
+void
+wrapper_code_generic_thumb()
+{
+ // we can never use r0-r11, neither the stack
+ asm volatile(
+ // preserve the registers
+ "push {r0-r11, lr}\n"
+
+ "ldr r0, tfun\n" // load the function pointer to r0
+ "ldr r1, tname\n" // load the address of the functions name to r1
+ "ldr r2, tstr\n" // load the string to print
+ "ldr r4, ttc\n" // load the address of trace_callback to r4
+ "blx r4\n" // call trace_callback
+
+ // restore the registers
+ "pop {r0-r11, lr}\n"
+ "ldr pc, tfun\n" // jump to function
+
+ // dummy instructions, this is where we locate our pointers
+ "tname: .word 0xFFFFFFFF\n" // name of function to call
+ "tfun: .word 0xFFFFFFFF\n" // function to call
+ "ttc: .word 0xFFFFFFFF\n" // address of trace_callback
+ "tstr: .word 0xFFFFFFFF\n" // the string being printed in trace_callback
+ );
+}
+#endif
+
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/common/wrappers.c
^
|
@@ -100,9 +100,22 @@
void *create_wrapper(const char *symbol, void *function, int wrapper_type)
{
size_t wrapper_size = 0;
+#ifdef __arm__
void *wrapper_code = (void*)((uint32_t)wrapper_code_generic & 0xFFFFFFFE);
+#elif defined(__aarch64__)
+ void *wrapper_code = (void*)(wrapper_code_generic);
+#endif
void *wrapper_addr = NULL;
int helper = 0;
+ int thumb_fixup = 0;
+
+#ifdef __arm__
+ if ((uint32_t)function & 1) {
+ // thumb
+ wrapper_code = (void*)((uint32_t)wrapper_code_generic_thumb & 0xFFFFFFFE);
+ thumb_fixup = 1;
+ }
+#endif
const char *msg = NULL;
@@ -136,7 +149,7 @@
wrapper_size = get_wrapper_code_size(wrapper_code);
// 4 additional longs for data storage, see below
- wrapper_size += 4 * sizeof(uint32_t);
+ wrapper_size += 4 * sizeof(uintptr_t);
// reserve memory for the generated wrapper
wrapper_addr = mmap(NULL, wrapper_size,
@@ -153,17 +166,17 @@
memcpy(wrapper_addr, wrapper_code, wrapper_size);
// Helper = offset of data fields in wrapper_addr (interpreted as int32_t)
- helper = wrapper_size / sizeof(uint32_t) - 4;
+ helper = wrapper_size / sizeof(uintptr_t) - 4;
switch(wrapper_type)
{
case WRAPPER_HOOKED:
case WRAPPER_UNHOOKED:
case WRAPPER_DYNHOOK:
- ((int32_t*)wrapper_addr)[helper++] = (uint32_t)symbol;
- ((int32_t*)wrapper_addr)[helper++] = (uint32_t)function;
- ((int32_t*)wrapper_addr)[helper++] = (uint32_t)trace_callback;
- ((int32_t*)wrapper_addr)[helper++] = (uint32_t)msg;
+ ((uintptr_t*)wrapper_addr)[helper++] = (uintptr_t)symbol;
+ ((uintptr_t*)wrapper_addr)[helper++] = (uintptr_t)function;
+ ((uintptr_t*)wrapper_addr)[helper++] = (uintptr_t)trace_callback;
+ ((uintptr_t*)wrapper_addr)[helper++] = (uintptr_t)msg;
break;
default:
assert(0);
@@ -172,7 +185,7 @@
register_wrapper(wrapper_addr, wrapper_size, symbol, wrapper_type);
- return (void*)wrapper_addr;
+ return (void*)wrapper_addr + thumb_fixup;
}
void release_all_wrappers()
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/configure.ac
^
|
@@ -61,7 +61,7 @@
AM_CONDITIONAL( [WANT_TRACE], [test x"$trace" = x"yes"])
AC_ARG_ENABLE(arm_tracing,
- [ --enable-arm-tracing Enable ARM (32-bit only) tracing, useful for understanding what the blob is doing, currently only the mm linker is supported. (default=disabled)],
+ [ --enable-arm-tracing Enable ARM (both 32 and 64-bit) tracing, useful for understanding what the blob is doing, currently only the mm linker is supported. (default=disabled)],
[arm_tracing=$enableval],
[arm_tracing="no"])
AM_CONDITIONAL([WANT_ARM_TRACING], [test x"$arm_tracing" = x"yes"])
@@ -171,11 +171,6 @@
],
[
PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit)
- AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [false])
- AM_CONDITIONAL([HAS_WIFI_LEGACY_HEADERS], [false])
- AM_CONDITIONAL([HAS_HWCOMPOSER2_HEADERS], [false])
- AM_CONDITIONAL([HAS_GRALLOC1_HEADER], [false])
- AM_CONDITIONAL([HAS_VIBRATOR_HEADER], [false])
AC_SUBST([ANDROID_HEADERS_PKGCONFIG], [android-headers])
]
)
@@ -184,6 +179,19 @@
AC_CHECK_HEADERS(android-config.h,,AC_MSG_ERROR(required header file is missing))
AC_CHECK_HEADERS(android-version.h,,AC_MSG_ERROR(required header file is missing))
+if test x$ac_with_android_headers == x""; then
+ AC_CHECK_HEADERS(libnfc-nxp/phLibNfc.h, HAS_LIBNFC_NXP_HEADERS=yes)
+ AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [test x"$HAS_LIBNFC_NXP_HEADERS" = x"yes"])
+ AC_CHECK_HEADERS(hardware_legacy/wifi.h, HAS_WIFI_LEGACY_HEADERS=yes)
+ AM_CONDITIONAL([HAS_WIFI_LEGACY_HEADERS], [test x"$HAS_WIFI_LEGACY_HEADERS" = x"yes"])
+ AC_CHECK_HEADERS(hardware/hwcomposer2.h, HAS_HWCOMPOSER2_HEADERS=yes, HAS_HWCOMPOSER2_HEADERS=no, [# include <stdbool.h>])
+ AM_CONDITIONAL([HAS_HWCOMPOSER2_HEADERS], [test x"$HAS_HWCOMPOSER2_HEADERS" = x"yes"])
+ AC_CHECK_HEADERS(hardware/gralloc1.h, HAS_GRALLOC1_HEADER=yes)
+ AM_CONDITIONAL([HAS_GRALLOC1_HEADER], [test x"$HAS_GRALLOC1_HEADER" = x"yes"])
+ AC_CHECK_HEADERS(hardware_legacy/vibrator.h, HAS_VIBRATOR_HEADER=yes)
+ AM_CONDITIONAL([HAS_VIBRATOR_HEADER], [test x"$HAS_VIBRATOR_HEADER" = x"yes"])
+fi
+
# AC_AWK_CPP
AC_DEFUN([AC_AWK_CPP],
[AC_LANG_PREPROC_REQUIRE()dnl
@@ -234,6 +242,7 @@
AC_MSG_NOTICE("Android headers version is $android_headers_major.$android_headers_minor.$android_headers_patch")
# Add automake tests for version/API needs here that you need in code, including test .am's
+AM_CONDITIONAL([HAS_ANDROID_10_0_0],[test $android_headers_major -ge 10 -a $android_headers_minor -ge 0 ])
AM_CONDITIONAL([HAS_ANDROID_9_0_0], [test $android_headers_major -ge 9 -a $android_headers_minor -ge 0 ])
AM_CONDITIONAL([HAS_ANDROID_8_0_0], [test $android_headers_major -ge 8 -a $android_headers_minor -ge 0 ])
AM_CONDITIONAL([HAS_ANDROID_7_0_0], [test $android_headers_major -ge 7 -a $android_headers_minor -ge 0 ])
@@ -269,6 +278,7 @@
common/mm/Makefile
common/n/Makefile
common/o/Makefile
+ common/q/Makefile
egl/egl.pc
egl/Makefile
egl/platforms/Makefile
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/egl/egl.c
^
|
@@ -194,7 +194,7 @@
struct _EGLDisplay *display = hybris_egl_display_get_mapping(dpy);
win = ws_CreateWindow(win, display);
- assert(((struct ANativeWindowBuffer *) win)->common.magic == ANDROID_NATIVE_WINDOW_MAGIC);
+ assert(((struct ANativeWindow *) win)->common.magic == ANDROID_NATIVE_WINDOW_MAGIC);
HYBRIS_TRACE_BEGIN("native-egl", "eglCreateWindowSurface", "");
EGLSurface result = (*_eglCreateWindowSurface)(dpy, config, win, attrib_list);
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/egl/platforms/common/nativewindowbase.cpp
^
|
@@ -275,6 +275,9 @@
case NATIVE_WINDOW_IS_VALID: return "NATIVE_WINDOW_IS_VALID";
case NATIVE_WINDOW_BUFFER_AGE: return "NATIVE_WINDOW_BUFFER_AGE";
#endif
+#if ANDROID_VERSION_MAJOR>=9
+ case NATIVE_WINDOW_MAX_BUFFER_COUNT: return "NATIVE_WINDOW_MAX_BUFFER_COUNT";
+#endif
default: return "NATIVE_UNKNOWN_QUERY";
}
}
@@ -329,6 +332,13 @@
*value = 2;
return NO_ERROR;
#endif
+#if ANDROID_VERSION_MAJOR>=9
+ case NATIVE_WINDOW_MAX_BUFFER_COUNT:
+ // The default maximum count of BufferQueue items.
+ // See android::BufferQueueDefs::NUM_BUFFER_SLOTS.
+ *value = 64;
+ return NO_ERROR;
+#endif
}
TRACE("EGL error: unkown window attribute! %i", what);
*value = 0;
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/egl/platforms/null/eglplatform_null.c
^
|
@@ -35,7 +35,11 @@
{
if (win == 0)
{
+#if (ANDROID_VERSION_MAJOR <= 7)
return android_createDisplaySurface();
+#else
+ return win;
+#endif
}
else
return win;
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/egl/platforms/wayland/wayland_window.cpp
^
|
@@ -90,8 +90,8 @@
void WaylandNativeWindow::resize(unsigned int width, unsigned int height)
{
lock();
- this->m_defaultWidth = width;
- this->m_defaultHeight = height;
+ this->m_defaultWidth = m_width = width;
+ this->m_defaultHeight = m_height = height;
unlock();
}
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/include/hybris/common/dlfcn.h
^
|
@@ -26,6 +26,7 @@
void *hybris_dlsym(void *handle, const char *symbol);
int hybris_dlclose(void *handle);
char *hybris_dlerror(void);
+int hybris_dladdr(const void *addr, void *info);
#ifdef __cplusplus
}
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/libsync/sync.c
^
|
@@ -23,6 +23,20 @@
#include <android-version.h>
+#if (ANDROID_VERSION_MAJOR >= 10)
+#include <linux/sync_file.h>
+struct sync_file_info* sync_file_info(int32_t fd);
+static inline struct sync_fence_info* sync_get_fence_info(const struct sync_file_info* info) {
+// This header should compile in C, but some C++ projects enable
+// warnings-as-error for C-style casts.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+ return (struct sync_fence_info *)(uintptr_t)(info->sync_fence_info);
+#pragma GCC diagnostic pop
+}
+void sync_file_info_free(struct sync_file_info* info);
+#endif
+
#if (ANDROID_VERSION_MAJOR <= 7)
#include <linux/sync.h>
#include <linux/sw_sync.h>
@@ -99,6 +113,26 @@
#endif //(ANDROID_VERSION_MAJOR >= 8)
+#if (ANDROID_VERSION_MAJOR >= 10)
+struct sync_fence_info_data {
+ uint32_t len;
+ char name[32];
+ int32_t status;
+ uint8_t pt_info[0];
+};
+struct sync_pt_info {
+ uint32_t len;
+ char obj_name[32];
+ char driver_name[32];
+ int32_t status;
+ uint64_t timestamp_ns;
+ uint8_t driver_data[0];
+};
+struct sync_fence_info_data* sync_fence_info(int fd);
+struct sync_pt_info* sync_pt_info(struct sync_fence_info_data* info, struct sync_pt_info* itr);
+void sync_fence_info_free(struct sync_fence_info_data* info);
+#endif
+
extern size_t strlcpy(char *dst, const char *src, size_t siz);
int sync_wait(int fd, int timeout)
|
[-]
[+]
|
Changed |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/tests/Makefile.am
^
|
@@ -16,10 +16,21 @@
test_opencl \
test_wifi \
test_hwcomposer \
- test_nfc
+ test_nfc \
+ test_dlopen
+
+
+test_dlopen_SOURCES = test_dlopen.c
+test_dlopen_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/hybris/include \
+ -I$(top_srcdir)/include/android
+test_dlopen_LDADD = \
+ $(top_builddir)/common/libhybris-common.la \
+ $(top_builddir)/hardware/libhardware.la
test_audio_SOURCES = test_audio.c
-test_audio_CFLAGS = \
+test_audio_CFLAGS = -std=c99\
-I$(top_srcdir)/include \
-I$(top_srcdir)/include/android
test_audio_LDADD = \
@@ -85,6 +96,7 @@
$(top_builddir)/egl/platforms/common/libhybris-eglplatformcommon.la \
$(top_builddir)/egl/libEGL.la \
$(top_builddir)/glesv2/libGLESv2.la \
+ $(top_builddir)/hardware/libhardware.la \
$(top_builddir)/libsync/libsync.la
if HAS_HWCOMPOSER2_HEADERS
test_glesv2_CXXFLAGS += \
@@ -116,6 +128,7 @@
$(top_builddir)/egl/platforms/common/libhybris-eglplatformcommon.la \
$(top_builddir)/egl/libEGL.la \
$(top_builddir)/glesv2/libGLESv2.la \
+ $(top_builddir)/hardware/libhardware.la \
$(top_builddir)/libsync/libsync.la
if HAS_HWCOMPOSER2_HEADERS
test_glesv3_CXXFLAGS += \
|
[-]
[+]
|
Added |
_service:tar_git:libhybris-0.0.5.42.tar.bz2/libhybris/hybris/tests/test_dlopen.c
^
|
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Zhongmin Wu <vwzm@live.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <hybris/common/binding.h>
+#include <dlfcn.h>
+#include <EGL/egl.h>
+#include <stdio.h>
+#include <stddef.h>
+
+
+int main(int argc, char **argv) {
+
+ int i = 0;
+ char *libname = "libc.so";
+
+ if (argc > 1) {
+ libname = argv[1];
+ }
+
+ void *handler = android_dlopen(libname, RTLD_LAZY);
+ printf("android %s is %p\n", libname,handler);
+ return 0;
+}
|