diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/changelog libhybris-0.1.0+git20151016+6d424c9/debian/changelog --- libhybris-0.1.0+git20151016+6d424c9/debian/changelog 2016-04-25 07:56:49.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/changelog 2016-08-10 06:28:10.000000000 +0000 @@ -1,4 +1,189 @@ -libhybris (0.1.0+git20151016+6d424c9-0ubuntu10~overlay1) vivid; urgency=medium +libhybris (0.1.0+git20151016+6d424c9-0ubuntu22~vivid1) vivid; urgency=medium + + * Backport to vivid stable overlay PPA + + -- Alfonso Sanchez-Beato (email Canonical) Wed, 10 Aug 2016 08:24:48 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu22~xenial1) xenial; urgency=medium + + [ You-Sheng Yang ] + * linker: disable linker probing when unavailable + * linker: remove /system/lib prefix from lib paths + * configure: use lib64 for DEFAULT_HYBRIS_LD_LIBRARY_PATH on arm64 + * compat: build arm64 flavor when available + + -- Simon Fels Fri, 05 Aug 2016 18:47:48 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu21) yakkety; urgency=medium + + [ Alfonso Sanchez-Beato ] + * compat: media: add bool macro definition + + -- Simon Fels Wed, 13 Jul 2016 08:35:49 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu20) yakkety; urgency=medium + + [ Alfonso Sanchez-Beato ] + * hybris: common: remove hooks for signal handling + + [ Simon Fels ] + * hybris: wifi: add new API method to send driver command + + -- Simon Fels Thu, 07 Jul 2016 10:40:38 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu19) yakkety; urgency=medium + + [ Bin Li ] + * hybris: common: Add hooks to support scandir + + [ Simon Fels ] + * hybris: common: remove old and unused gb and ics linkers + * hybris: common: mm: include strlcat/strlcpy to avoid linke time issues + * hybris: common: mm: drop unneeded compile time definitions + + -- Simon Fels Wed, 29 Jun 2016 17:41:10 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu18) yakkety; urgency=medium + + [ Boleslaw Tokarski ] + * [properties] An off-by-one error in prop handling + + [ Gunnar Sletta ] + * [glesv2] Wrap glGetString() and return GL_VERSION == 2.0 + + -- Simon Fels Wed, 22 Jun 2016 13:27:17 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu17) yakkety; urgency=medium + + * Revert "Fix resolving the GLEsv2 functions at link time" + * hybris: common: fine tune dynamic linker load process + * hybris: glesv2: load symbols on demand + * hybris: glesv2: drop redefined symbols + * hybris: glesv2: really drop all unneeded symbols + * hybris: glesv2: revert back to version without using GNU indirect feature + * hybris: common: more fine tuning for runtime linker loading + * hybris: common: use correct property name for device name + * hybris: common: force SDK version 19 for cooler too + * hybris: common: add env variable to override selected SDK version + * hybris: common: use debug log statement rather than plain printf + * hybris: common: rename variable containing hooks for all devices + * hybris: glesv2: don't return anything in functions with void as return type + * hybris: common: enable linker overrides only by configure option + * debian: enable ubuntu linker overrides only for armhf + + -- Simon Fels Tue, 21 Jun 2016 11:58:45 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu16) yakkety; urgency=medium + + * No change release. + + -- Simon Fels Wed, 15 Jun 2016 17:48:02 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu15) yakkety; urgency=medium + + * hybris: mm: use recursive mutex for dlopen/.. locking + * hybris: common: add support for dynamic linker loading at runtime + + -- Simon Fels Wed, 15 Jun 2016 16:55:55 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu14) yakkety; urgency=medium + + [ Ondrej Kubik ] + * Fix Android 6.x build for Android Build System. + + [ Rex Tsai (蔡志展) ] + * Fix MediaCodecSource::Create() API change for Android 6.0.0_r1. + + [ Simon Fels ] + * hybris: introduce experimental configuration feature + * hybris: note used android version in configure summary + * hybris: common: import marshmallow linker + * hybris: common: enable building marshmellow linker + * hybris: common: make marshmellow linker building + * hybris: common: mm: drop support for libs inside zip archives + * hybris: common: mm: get rid of sys/limits.h copy + * hybris: common: mm: disable tls initialization + * hybris: common: mm: disable debuggerd connection + * hybris: common: mm: export android_* dlfcn functions for use from C + * hybris: common: add hybris prefix for our hook processing method + * hybris: common: mm: add symbol hooking functionality + * hybris: common: mm: redirect all linker logs to stdout + * hybris: common: mm: use HYBRIS_LD_DEBUG to enable debug output + * hybris: common: mm: get linker building on arm platforms + * hybris: common: build with c++ support + * hybris: common: mm: further enablement work + * hybris: common: mm: don't memset class instance + * hybris: common: mm: disable linker internal memory mgmt for small objects + * hybris: common: mm: respect hybris specific library paths only + * hybris: common: mm: replace LINKER_DEBUG with TRACE_DEBUG + * hybris: mention experimental configure option in summary + * hybris: common: add missing libs we have to link to + * hybris: common: mm: switch from fprintf to DEBUG + * hybris: common: mm: disable some more code parts we don't use + * tests: add missing pthread to LDADD for test_nfc + * hybris: common: add c'tor to initialize linker logging + * hybris: common: add ability to deliver hooks from the outside + * hybris: common: mm: add missing line ending for error messages + * hybris: common: mm: fix compliation in x86 + * hybris: common: really make hooking work + * hybris: common: make hook handler availble for C++ + * hybris: common: deliver symbol requester through our hooks too + * hybris: egl: don't create surface mapping when creation failed + * hybris: hooks: hook a few more symbols for Android 6 support + * hybris: common: switch hook prefix to _hybris_hook_ + * hybris: common: add tracing support for our hooks + * utils: update load-sym-files gdb command to python3 + * hybris: common: convert addrinfo struct correctly + * hybris: common: respect unsigned nature of size_t + * hybris: common: add tracing for sysconf hook + * hybris: common: add proper copyright header for sysconf implementation + * hybris: common: add more hooks to let string.* bionic tests pass + * hybris: common: add new keys for sysconf + * hybris: common: add a few more necessary hooks + * hybris: common: improve tracing for a few hooks + * hybris: use pthread rather than lpthread to link with pthread lib + * hybris: common: mm: drop old ARCH_FLAGS we don't need + * hybris: common: add hook for strcmp to fail on nullptr + * hybris: common: fix printf format + * hybris: common: add more necessary hooks + * debian: install load_sym_files.py gdb helper script + * debian: enable mm linker by default + * hybris: detect arm64 architecture at configuration time + * hybris: common: mm: use correct names for relocation types + * debian: package libGLESv1_CM.so + + [ Giulio Camuffo ] + * Fix resolving the GLEsv2 functions at link time + + [ Simon Fels ] + * debian: update copyright file + * debian: bump standards version to 3.9.7 + + -- Simon Fels Tue, 14 Jun 2016 09:52:43 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu13) xenial; urgency=medium + + * hybris: common: stub: don't assert but return error + + -- Simon Fels Mon, 09 May 2016 16:09:26 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu12) xenial; urgency=medium + + * debian: split out arch specific configuration flags + + -- Simon Fels Fri, 06 May 2016 09:48:53 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu11) xenial; urgency=medium + + * hybris: common: add stub linker implementation + * debian: split out common parts of the default configuration + * debian: add build support for arm64 + * hybris: add README file stating which architectures are supported + * hybris: autotools want it to be README + + -- Simon Fels Tue, 03 May 2016 17:29:41 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu10) xenial; urgency=medium * debian: add missing hybris/common include directory diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/control libhybris-0.1.0+git20151016+6d424c9/debian/control --- libhybris-0.1.0+git20151016+6d424c9/debian/control 2016-04-25 07:56:53.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/control 2016-08-10 06:28:16.000000000 +0000 @@ -10,13 +10,13 @@ pkg-config, libgles2-mesa-dev, libwayland-dev -Standards-Version: 3.9.5 +Standards-Version: 3.9.7 Section: libs Vcs-Git: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris Vcs-Browser: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris/ Package: libandroid-properties1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Description: Library to provide access to get, set and list Android properties @@ -26,7 +26,7 @@ Package: libandroid-properties-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libandroid-properties1 (= ${binary:Version}), ${misc:Depends} Description: Development headers files for libandroid-properties @@ -34,7 +34,7 @@ set or list the Android properties. Package: libmedia1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu24) @@ -49,7 +49,7 @@ Package: libmedia-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libmedia1 (= ${binary:Version}), android-headers (>= 4.4.2), ${misc:Depends} @@ -63,7 +63,7 @@ glibc systems. Package: libhardware2 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -78,7 +78,7 @@ Package: libhardware-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhardware2 (= ${binary:Version}), android-headers (>= 4.4.2), ${misc:Depends} @@ -93,7 +93,7 @@ glibc systems. Package: libhybris-common1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -107,7 +107,7 @@ Package: libhybris-common-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris-common1 (= ${binary:Version}), ${misc:Depends} Replaces: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -121,7 +121,7 @@ glibc systems. Package: libhybris -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libandroid-properties1 (= ${binary:Version}), libhardware2, libmedia1, @@ -133,7 +133,7 @@ Package: libhybris-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), android-headers (>= 4.4.2), libandroid-properties-dev (= ${binary:Version}), @@ -151,7 +151,7 @@ Package: libhybris-utils Section: utils -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} @@ -163,7 +163,7 @@ Package: libhybris-test Section: devel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/control.in libhybris-0.1.0+git20151016+6d424c9/debian/control.in --- libhybris-0.1.0+git20151016+6d424c9/debian/control.in 2016-04-21 09:07:32.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/control.in 2016-08-05 16:46:15.000000000 +0000 @@ -10,13 +10,13 @@ pkg-config, libgles2-mesa-dev, libwayland-dev -Standards-Version: 3.9.5 +Standards-Version: 3.9.7 Section: libs Vcs-Git: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris Vcs-Browser: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris/ Package: libandroid-properties1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Description: Library to provide access to get, set and list Android properties @@ -26,7 +26,7 @@ Package: libandroid-properties-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libandroid-properties1 (= ${binary:Version}), ${misc:Depends} Description: Development headers files for libandroid-properties @@ -34,7 +34,7 @@ set or list the Android properties. Package: libmedia1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu24) @@ -49,7 +49,7 @@ Package: libmedia-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libmedia1 (= ${binary:Version}), android-headers (>= 4.4.2), ${misc:Depends} @@ -63,7 +63,7 @@ glibc systems. Package: libhardware2 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -78,7 +78,7 @@ Package: libhardware-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhardware2 (= ${binary:Version}), android-headers (>= 4.4.2), ${misc:Depends} @@ -93,7 +93,7 @@ glibc systems. Package: libhybris-common1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -107,7 +107,7 @@ Package: libhybris-common-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris-common1 (= ${binary:Version}), ${misc:Depends} Replaces: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -121,7 +121,7 @@ glibc systems. Package: libhybris -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libandroid-properties1 (= ${binary:Version}), libhardware2, libmedia1, @@ -133,7 +133,7 @@ Package: libhybris-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), android-headers (>= 4.4.2), libandroid-properties-dev (= ${binary:Version}), @@ -151,7 +151,7 @@ Package: libhybris-utils Section: utils -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} @@ -163,7 +163,7 @@ Package: libhybris-test Section: devel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/copyright libhybris-0.1.0+git20151016+6d424c9/debian/copyright --- libhybris-0.1.0+git20151016+6d424c9/debian/copyright 2016-04-21 09:07:32.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/copyright 2016-08-05 16:46:15.000000000 +0000 @@ -2,106 +2,361 @@ Upstream-Name: libhybris Source: https://github.com/libhybris/libhybris -Files: compat/surface_flinger/* hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h hybris/include/hybris/surface_flinger/surface_flinger_compatibility_layer.h hybris/sf/sf.c hybris/tests/test_sf.c -Copyright: 2013 Canonical Ltd -License: Apache 2.0 - -Files: compat/ui/* hybris/egl/eglhybris.h hybris/hardware/hardware.c hybris/include/hybris/ui/ui_compatibility_layer.h hybris/ui/ui.c hybris/tests/test_lights.c hybris/tests/test_sensors.c hybris/tests/test_ui.c -Copyright: 2012-2013 Simon Busch -License: Apache 2.0 +Files: * +Copyright: 2012-2014, 2016, Canonical Ltd +License: Apache-2.0 + +Files: compat/media/SimplePlayer.cpp + compat/media/SimplePlayer.h + compat/media/codec.cpp +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: compat/media/media_recorder.cpp + compat/media/media_recorder.h +Copyright: 2013, 2014, Canonical Ltd + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: compat/ui/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 -Files: hybris/include/hybris/common/binding.h -Copyright: 2013 Simon Busch - 2012 Canonical Ltd -License: Apache 2.0 +Files: hybris/common/* +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/egl/platforms/common/native_handle.c -Copyright: 2007 The Android Open Source Project -License: Apache 2.0 +Files: hybris/common/dlfcn.c +Copyright: 2013, Intel Corporation +License: Apache-2.0 + +Files: hybris/common/gingerbread/NOTICE + hybris/common/gingerbread/dlfcn.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 Files: hybris/common/hooks.c -Copyright: 2012 Carsten Munk - 2012 Canonical Ltd -License: Apache 2.0 +Copyright: 2013, Christophe Chapuis + 2012, Carsten Munk + 2012, Canonical Ltd +License: Apache-2.0 + +Files: hybris/common/hooks_shm.c +Copyright: 2013, Christophe Chapuis + 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/common/hooks_shm.h +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/common/ics/dlfcn.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/jb/dlfcn.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/logging.c + hybris/common/logging.h +Copyright: 2013, Thomas Perl +License: Apache-2.0 + +Files: hybris/common/mm/* +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 -Files: hybris/tests/test_gps.c -Copyright: 2013 Jolla Mobile -License: Apache 2.0 +Files: hybris/common/mm/bionic/* +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/common/logging.* -Copyright: 2013 Thomas Perl -License: Apache 2.0 - -Files: hybris/egl/platforms/fbdev/fbdev_window.* -Copyright: 2013 libhybris -License: Apache 2.0 +Files: hybris/common/mm/bionic/libc/include/android/dlext.h +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/mm/bionic/libc/private/* +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/mm/bionic/libc/private/ThreadLocalBuffer.h + hybris/common/mm/bionic/libc/private/__get_tls.h + hybris/common/mm/bionic/libc/private/bionic_asm.h + hybris/common/mm/bionic/libc/private/bionic_auxv.h + hybris/common/mm/bionic/libc/private/bionic_futex.h + hybris/common/mm/bionic/libc/private/bionic_lock.h + hybris/common/mm/bionic/libc/private/bionic_mbstate.h + hybris/common/mm/bionic/libc/private/bionic_ssp.h + hybris/common/mm/bionic/libc/private/bionic_time.h + hybris/common/mm/bionic/libc/private/bionic_time_conversions.h + hybris/common/mm/bionic/libc/private/bionic_tls.h + hybris/common/mm/bionic/libc/private/libc_events.h + hybris/common/mm/bionic/libc/private/libc_logging.h +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/egl/platforms/wayland/eglplatform_wayland.cpp hybris/egl/platforms/wayland/wayland_window.h hybris/egl/platforms/wayland/wayland_window.cpp -Copyright: 2013 Jolla Ltd -License: LGPL-2.1 +Files: hybris/common/mm/hybris_compat.cpp + hybris/common/mm/hybris_compat.h + hybris/common/mm/linker.cpp + hybris/common/mm/linker.h + hybris/common/mm/linker_debug.h + hybris/common/mm/linker_phdr.cpp + hybris/common/mm/linker_phdr.h + hybris/common/mm/rt.cpp +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/common/properties.* hybris/egl/egl.c hybris/glesv2/glesv2.c hybris/tests/test_glesv2.c hybris/tests/test_egl.c -Copyright: 2012 Carsten Munk -License: Apache 2.0 +Files: hybris/common/strlcat.c +Copyright: 1998, Todd C. Miller +License: ISC -Files: hybris/include/CL/* hybris/include/KHR/* hybris/include/EGL/* hybris/include/VG/* hybris/include/GL/glxext.h hybris/include/GL/glext.h hybris/include/GL/wglext.h -Copyright: 2007-2012 The Khronos Group Inc -License: X11/MIT +Files: hybris/common/strlcpy.c +Copyright: 1998, Todd C. Miller +License: ISC -Files: hybris/include/GL/glx.h hybris/include/GL/glx_mangle.h hybris/include/GL/osmesa.h -Copyright: 1999-2006 Brian Paul -License: X11/MIT +Files: hybris/common/stub/* +Copyright: 2012-2014, 2016, Canonical Ltd +License: Apache-2.0 + +Files: hybris/common/sysconf.c +Copyright: 2013, Adrian Negreanu +License: Apache-2.0 + +Files: hybris/egl/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/egl/egl.c +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/egl/eglhybris.h +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/egl/platforms/* +Copyright: 2013, libhybris +License: Apache-2.0 + +Files: hybris/egl/platforms/common/* +Copyright: 2012, Collabora, Ltd +License: MIT2 + Permission to use, copy, modify, distribute, and sell this software and + its documentation for any purpose is hereby granted without fee, provided + that the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation, and that the name of the copyright holders not be used in + advertising or publicity pertaining to distribution of the software + without specific, written prior permission. The copyright holders make + no representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + . + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Files: hybris/egl/platforms/common/hybris_nativebufferext.h +Copyright: 2013, Jolla Ltd + 2011, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/egl/platforms/common/native_handle.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/egl/platforms/common/server_wlegl_handle.h + hybris/egl/platforms/common/windowbuffer.cpp + hybris/egl/platforms/common/windowbuffer.h +Copyright: 2012, Collabora, Ltd +License: BSD-2-clause + +Files: hybris/egl/platforms/wayland/* +Copyright: 2013, Jolla Ltd +License: LGPL-2.1 + +Files: hybris/egl/ws.c +Copyright: 2013, libhybris +License: Apache-2.0 + +Files: hybris/glesv1/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/glesv2/* +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/hardware/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/include/* +Copyright: 2007-2012, The Khronos Group Inc +License: Expat + +Files: hybris/include/EGL/eglmesaext.h +Copyright: 2008, Tungsten Graphics, Inc., Cedar Park, Texas +License: Expat Files: hybris/include/GL/gl.h -Copyright: 1999-2006 Brian Paul - 2009 VMware, Inc. -License: X11/MIT +Copyright: 2009, VMware, Inc. + 1999-2006, Brian Paul +License: Expat + +Files: hybris/include/GL/glx.h + hybris/include/GL/glx_mangle.h + hybris/include/GL/osmesa.h +Copyright: 1999-2006, Brian Paul +License: Expat + +Files: hybris/include/GL/internal/* +Copyright: IBM Corporation 2004, / 2007-2008, Red Hat, Inc / 1998-1999, Precision Insight, Inc., Cedar Park, Texas +License: Expat + +Files: hybris/include/GL/internal/sarea.h +Copyright: 2000, VA Linux Systems, Inc + 1998, 1999, Precision Insight, Inc., Cedar Park, Texas +License: Expat Files: hybris/include/GL/wmesa.h -Copyright: 1995-1998 Brian Paul +Copyright: 1995-1998, Brian Paul License: LGPL-2+ -Files: hybris/include/GL/internal/sarea.h -Copyright: 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - 2000 VA Linux Systems, Inc. -License: X11/MIT - -Files: hybris/include/GL/internal/dri_interface.h -Copyright: 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - 2007-2008 Red Hat, Inc. - 2004 IBM Corporation -License: X11/MIT +Files: hybris/include/GLES/* +Copyright: 2010-2012 Silicon Graphics, Inc +License: SGI-2.0 -Files: hybris/include/GLES2/gl2.h hybris/include/GLES2/gl2ext.h hybris/include/GLES2/gl2platform.h hybris/include/GLES/gl.h hybris/include/GLES/glext.h hybris/include/GLES/glplatform.h +Files: hybris/include/GLES2/* Copyright: 2010-2012 Silicon Graphics, Inc License: SGI-2.0 - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is furnished - to do so, subject to the following conditions: - . - The above copyright notice including the dates of first publication and either - this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ - shall be included in all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. - . - Except as contained in this notice, the name of Silicon Graphics, Inc. shall - not be used in advertising or otherwise to promote the sale, use or other - dealings in this Software without prior written authorization from Silicon - Graphics, Inc. + +Files: hybris/include/VG/* +Copyright: 2008, The Khronos Group Inc +License: X11/MIT + +Files: hybris/include/hybris/* +Copyright: 2012-2014, 2016, Canonical Ltd +License: Apache-2.0 + +Files: hybris/include/hybris/common/binding.h +Copyright: 2013, Simon Busch + 2013, Jolla Ltd. + 2012, Canonical Ltd +License: Apache-2.0 + +Files: hybris/include/hybris/common/dlfcn.h +Copyright: 2013, Intel Corporation +License: Apache-2.0 + +Files: hybris/include/hybris/common/floating_point_abi.h +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/include/hybris/dlfcn/* +Copyright: 2013, Intel Corporation +License: Apache-2.0 + +Files: hybris/include/hybris/properties/* +Copyright: 2013, Simon Busch + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/include/hybris/ui/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/libnfc_ndef_nxp/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/libnfc_nxp/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/libsync/* +Copyright: 2012, Google, Inc +License: Apache-2.0 + +Files: hybris/properties/* +Copyright: 2013, Simon Busch + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/properties/cache.c +Copyright: 2013, Simon Busch + 2013, Jolla Ltd. + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/properties/properties_p.h +Copyright: 2013, Jolla Ltd. +License: Apache-2.0 + +Files: hybris/properties/runtime_cache.c +Copyright: 2015, Jolla Ltd. + 2013, Simon Busch + 2013, Jolla Ltd. + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/tests/test_egl.c + hybris/tests/test_glesv2.c + hybris/tests/test_hwcomposer.cpp +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/tests/test_egl_configs.c +Copyright: 2013, Thomas Perl +License: Apache-2.0 + +Files: hybris/tests/test_gps.c + hybris/tests/test_nfc.c + hybris/tests/test_vibrator.c +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/tests/test_lights.c + hybris/tests/test_sensors.c + hybris/tests/test_ui.c +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/ui/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/utils/* +Copyright: 2013, 2014, Canonical Ltd + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/vibrator/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: utils/* +Copyright: 2013, Jolla Ltd + 2012, Thomas Perl ; 2012-10-19 libhybris version: +License: BSD-2-clause + +Files: utils/generate_wrapper_macros.py +Copyright: 2013, Jolla Ltd +License: BSD-2-clause Files: utils/load_sym_files.py -Copyright: 2013 Adrian Negreanu +Copyright: 2013, Adrian Negreanu License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -120,8 +375,19 @@ License version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. -Files: hybris/common/gingerbread/* hybris/common/ics/* hybris/common/jb/* -Copyright: 2007-2010 The Android Open Source Project +License: Apache-2.0 + 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. + License: BSD-2-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -146,30 +412,35 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Files: hybris/egl/platforms/common/wayland-android-client-protocol.h hybris/egl/platforms/common/wayland-android-protocol.c hybris/egl/platforms/common/server_wlegl_buffer.h hybris/egl/platforms/common/server_wlegl_buffer.cpp hybris/egl/platforms/common/server_wlegl.h hybris/egl/platforms/common/wayland-android.xml hybris/egl/platforms/common/server_wlegl_handle.cpp hybris/egl/platforms/common/wayland-android-server-protocol.h hybris/egl/platforms/common/server_wlegl.cpp hybris/egl/platforms/common/server_wlegl_private.h -Copyright: 2012 Collabora, Ltd. -License: MIT2 - Permission to use, copy, modify, distribute, and sell this software and - its documentation for any purpose is hereby granted without fee, provided - that the above copyright notice appear in all copies and that both that - copyright notice and this permission notice appear in supporting - documentation, and that the name of the copyright holders not be used in - advertising or publicity pertaining to distribution of the software - without specific, written prior permission. The copyright holders make - no representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied warranty. +License: Expat + The MIT License . - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to + whom the Software is furnished to do so, subject to the + following conditions: + . + The above copyright notice and this permission notice shall + be included in all copies or substantial portions of the + Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT + WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. -Files: hybris/common/strlcpy.c -Copyright: 1998 Todd C. Miller -License: ICS +License: ISC Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. @@ -182,24 +453,11 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -License: Apache 2.0 - 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. - -License: LGPL-2.1 +License: LGPL-2+ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1 - of the License. + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -212,14 +470,14 @@ Boston, MA 02110-1301 USA . On Debian systems, the full text of the GNU Lesser General Public - License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + License version 2 can be found in the file + `/usr/share/common-licenses/LGPL-2'. -License: LGPL-2+ +License: LGPL-2.1 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + License as published by the Free Software Foundation, version 2.1 + of the License. . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -232,8 +490,8 @@ Boston, MA 02110-1301 USA . On Debian systems, the full text of the GNU Lesser General Public - License version 2 can be found in the file - `/usr/share/common-licenses/LGPL-2'. + License version 2.1 can be found in the file + `/usr/share/common-licenses/LGPL-2.1'. License: X11/MIT Permission is hereby granted, free of charge, to any person obtaining a copy @@ -253,3 +511,29 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License: SGI-2.0 + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + . + The above copyright notice including the dates of first publication and either + this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ + shall be included in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + . + Except as contained in this notice, the name of Silicon Graphics, Inc. shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization from Silicon + Graphics, Inc. diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-common1.install libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-common1.install --- libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-common1.install 2016-04-21 09:07:32.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-common1.install 2016-08-05 16:46:15.000000000 +0000 @@ -1 +1,2 @@ usr/lib/*/libhybris-common.so.* +usr/lib/*/libhybris/linker/*.so diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/libhybris.install.in libhybris-0.1.0+git20151016+6d424c9/debian/libhybris.install.in --- libhybris-0.1.0+git20151016+6d424c9/debian/libhybris.install.in 2016-04-21 09:07:32.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris.install.in 2016-08-05 16:46:15.000000000 +0000 @@ -12,3 +12,4 @@ usr/lib/*/libwayland-egl.so.* #PKGLIBDIR# usr/lib/*/libEGL.so.* #PKGLIBDIR# usr/lib/*/libGLESv2.so.* #PKGLIBDIR# +usr/lib/*/libGLESv1_CM.so.* #PKGLIBDIR# diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-utils.install libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-utils.install --- libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-utils.install 2016-04-21 09:07:32.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-utils.install 2016-08-05 16:46:15.000000000 +0000 @@ -1,2 +1,3 @@ usr/bin/getprop usr/bin/setprop +utils/load_sym_files.py usr/share/libhybris/gdb/ diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/patches/debian-changes libhybris-0.1.0+git20151016+6d424c9/debian/patches/debian-changes --- libhybris-0.1.0+git20151016+6d424c9/debian/patches/debian-changes 2016-04-25 07:56:54.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/patches/debian-changes 2016-08-10 06:28:18.000000000 +0000 @@ -30,23 +30,27 @@ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris -@@ -7,6 +8,7 @@ LOCAL_SRC_FILES := camera_compatibility_ +@@ -7,6 +8,9 @@ LOCAL_SRC_FILES := camera_compatibility_ LOCAL_MODULE := libcamera_compat_layer LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include -@@ -30,6 +32,7 @@ LOCAL_SRC_FILES := direct_camera_test.cp +@@ -30,6 +34,9 @@ LOCAL_SRC_FILES := direct_camera_test.cp LOCAL_MODULE := direct_camera_test LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include \ -@@ -43,6 +46,7 @@ LOCAL_SHARED_LIBRARIES := \ +@@ -43,6 +50,7 @@ LOCAL_SHARED_LIBRARIES := \ libis_compat_layer \ libsf_compat_layer \ libcamera_compat_layer \ @@ -93,7 +97,7 @@ +#else +#include +#endif -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 +#include +#endif #include @@ -120,7 +124,7 @@ +using android::CompileTimeAssert; // So COMPILE_TIME_ASSERT works + +// From android::GLConsumer::FrameAvailableListener -+#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 + void CameraControl::onFrameAvailable(const android::BufferItem& item) +#else + void CameraControl::onFrameAvailable() @@ -209,7 +213,7 @@ - CameraControl* cc = new CameraControl(); + android::sp cc = new CameraControl(); cc->listener = listener; -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3 || ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3 || ANDROID_VERSION_MAJOR==5 || ANDROID_VERSION_MAJOR>=6 + cc->camera = android::Camera::connect(camera_id, android::String16("hybris"), android::Camera::USE_CALLING_UID); +#else cc->camera = android::Camera::connect(camera_id); @@ -392,7 +396,7 @@ new android::NativeBufferAlloc() ); -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + android::sp producer; + android::sp consumer; + android::BufferQueue::createBufferQueue(&producer, &consumer); @@ -414,7 +418,7 @@ + control->preview_texture = android::sp( + new android::GLConsumer( +#endif -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + consumer, + texture_id, + GL_TEXTURE_EXTERNAL_OES, @@ -442,7 +446,7 @@ + android::sp(control)); +#endif + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + control->camera->setPreviewTarget(producer); +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 control->camera->setPreviewTexture(control->preview_texture->getBufferQueue()); @@ -1291,15 +1295,17 @@ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris -@@ -9,6 +10,7 @@ LOCAL_SRC_FILES:= input_compatibility_la +@@ -9,6 +10,9 @@ LOCAL_SRC_FILES:= input_compatibility_la LOCAL_MODULE:= libis_compat_layer LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_SHARED_LIBRARIES := \ libinput \ -@@ -20,8 +22,24 @@ LOCAL_SHARED_LIBRARIES := \ +@@ -20,8 +24,24 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include \ @@ -1313,7 +1319,7 @@ +LOCAL_C_INCLUDES += frameworks/base/services/input +endif + -+HAS_LIBINPUTFLINGER := $(shell test $(ANDROID_VERSION_MAJOR) -eq 5 && echo true) ++HAS_LIBINPUTFLINGER := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) +ifeq ($(HAS_LIBINPUTFLINGER),true) +LOCAL_SHARED_LIBRARIES += libinputflinger libinputservice +LOCAL_C_INCLUDES += \ @@ -1326,11 +1332,13 @@ include $(BUILD_SHARED_LIBRARY) -@@ -36,6 +54,7 @@ LOCAL_SRC_FILES:= \ +@@ -36,6 +56,9 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE:= direct_input_test LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include \ @@ -1345,7 +1353,7 @@ +#if ANDROID_VERSION_MAJOR<=4 + #include "InputListener.h" + #include "InputReader.h" -+#elif ANDROID_VERSION_MAJOR==5 ++#elif ANDROID_VERSION_MAJOR>=5 + #include "inputflinger/InputListener.h" + #include "inputflinger/InputReader.h" +#endif @@ -1353,7 +1361,7 @@ #include "PointerController.h" #include "SpriteController.h" #include -@@ -48,10 +54,20 @@ public: +@@ -48,10 +54,28 @@ public: DefaultPointerControllerPolicy() { @@ -1370,27 +1378,35 @@ + ct, + SkAlphaType::kPremul_SkAlphaType), + 0); ++#elif ANDROID_VERSION_MAJOR==6 ++bitmap.setInfo( ++ SkImageInfo::Make(bitmap_width, ++ bitmap_height, ++ kRGBA_8888_SkColorType, ++ SkAlphaType::kPremul_SkAlphaType), ++ 0); ++ +#endif bitmap.allocPixels(); // Icon for spot touches -@@ -142,7 +158,11 @@ public: +@@ -142,7 +166,11 @@ public: mInputDevices = inputDevices; } +#if ANDROID_VERSION_MAJOR<=4 virtual android::sp getKeyboardLayoutOverlay(const android::String8& inputDeviceDescriptor) { -+#elif ANDROID_VERSION_MAJOR==5 ++#elif ANDROID_VERSION_MAJOR>=5 + virtual android::sp getKeyboardLayoutOverlay(const android::InputDeviceIdentifier& identifier) { +#endif return NULL; } -@@ -150,6 +170,12 @@ public: +@@ -150,6 +178,12 @@ public: return android::String8::empty(); } -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + virtual android::TouchAffineTransformation getTouchAffineTransformation(const android::String8& inputDeviceDescriptor, int32_t surfaceRotation) { + return android::TouchAffineTransformation(); + } @@ -1401,7 +1417,7 @@ int default_layer_for_touch_point_visualization; --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/Android.mk -@@ -0,0 +1,169 @@ +@@ -0,0 +1,179 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) +include $(LOCAL_PATH)/../Android.common.mk @@ -1425,9 +1441,9 @@ + frameworks/av/services/medialog \ + frameworks/av/services/camera/libcameraservice + -+HAS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) ++IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) + -+ifeq ($(HAS_ANDROID_5),true) ++ifeq ($(IS_ANDROID_5),true) +LOCAL_C_INCLUDES += system/media/camera/include + +# All devices having Android 5.x also have MediaCodecSource @@ -1438,7 +1454,9 @@ + +LOCAL_MODULE := camera_service + -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +include $(BUILD_EXECUTABLE) + @@ -1482,7 +1500,9 @@ + +LOCAL_MODULE:= libmedia_compat_layer +LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ @@ -1512,7 +1532,7 @@ + system/media/audio_utils/include \ + frameworks/av/services/camera/libcameraservice + -+IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -eq 5 && echo true) ++IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) +ifeq ($(IS_ANDROID_5),true) +LOCAL_C_INCLUDES += frameworks/native/include/media/openmax +endif @@ -1530,7 +1550,9 @@ + $(TOP)/$(MTK_PATH_SOURCE)/frameworks/av/include +endif + -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +include $(BUILD_SHARED_LIBRARY) + @@ -1544,7 +1566,9 @@ + +LOCAL_MODULE:= direct_media_test +LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include \ @@ -1568,7 +1592,9 @@ + libEGL \ + libGLESv2 + -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +include $(BUILD_EXECUTABLE) --- /dev/null @@ -2967,7 +2993,7 @@ +} --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/decoding_service.cpp -@@ -0,0 +1,366 @@ +@@ -0,0 +1,386 @@ +/* + * Copyright (C) 2014 Canonical Ltd + * @@ -3033,8 +3059,11 @@ + CHECK_INTERFACE(IDecodingService, data, reply); + sp gbc; + status_t res = getIGraphicBufferConsumer(&gbc); -+ ++#if ANDROID_VERSION_MAJOR>=6 ++ reply->writeStrongBinder(IInterface::asBinder(gbc)); ++#else + reply->writeStrongBinder(gbc->asBinder()); ++#endif + reply->writeInt32(res); + + return NO_ERROR; @@ -3044,7 +3073,11 @@ + sp gbp; + status_t res = getIGraphicBufferProducer(&gbp); + ++#if ANDROID_VERSION_MAJOR>=6 ++ reply->writeStrongBinder(IInterface::asBinder(gbp)); ++#else + reply->writeStrongBinder(gbp->asBinder()); ++#endif + reply->writeInt32(res); + + return NO_ERROR; @@ -3094,7 +3127,11 @@ + ALOGD("Entering %s", __PRETTY_FUNCTION__); + Parcel data, reply; + data.writeInterfaceToken(IDecodingService::getInterfaceDescriptor()); ++#if ANDROID_VERSION_MAJOR>=6 ++ data.writeStrongBinder(IInterface::asBinder(session)); ++#else + data.writeStrongBinder(session->asBinder()); ++#endif + data.writeInt32(handle); + remote()->transact(REGISTER_SESSION, data, &reply); + return NO_ERROR; @@ -3165,7 +3202,7 @@ + pid_t pid = IPCThreadState::self()->getCallingPid(); + ALOGD("Calling Pid: %d", pid); + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + *gbc = consumer; +#else + *gbc = buffer_queue; @@ -3179,7 +3216,7 @@ + pid_t pid = IPCThreadState::self()->getCallingPid(); + ALOGD("Calling Pid: %d", pid); + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + *gbp = producer; +#else + *gbp = buffer_queue; @@ -3193,8 +3230,13 @@ + ALOGD("Entering %s", __PRETTY_FUNCTION__); + + // Add session/handle to running clients map and connect death observer ++#if ANDROID_VERSION_MAJOR>=6 ++ status_t ret = IInterface::asBinder(session)->linkToDeath(sp(this)); ++ clientCbs.add(IInterface::asBinder(session), clients.valueFor(handle)); ++#else + status_t ret = session->asBinder()->linkToDeath(sp(this)); + clientCbs.add(session->asBinder(), clients.valueFor(handle)); ++#endif + clients.removeItem(handle); + + // Create a new BufferQueue instance so that the next created client plays @@ -3209,11 +3251,15 @@ + ALOGD("Entering %s", __PRETTY_FUNCTION__); + if (session != NULL) + { ++#if ANDROID_VERSION_MAJOR>=6 ++ IInterface::asBinder(session)->unlinkToDeath(this); ++#else + session->asBinder()->unlinkToDeath(this); ++#endif + session.clear(); + // Reset the BufferQueue instance so that the next created client plays + // video correctly -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + producer.clear(); + consumer.clear(); +#else @@ -3231,7 +3277,7 @@ + sp g_buffer_alloc(new GraphicBufferAlloc()); + + // This BuferQueue is shared between the client and the service -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + BufferQueue::createBufferQueue(&producer, &consumer); +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + sp native_alloc(new NativeBufferAlloc()); @@ -3240,7 +3286,7 @@ + buffer_queue = new BufferQueue(NULL); + ALOGD("buffer_queue: %p", (void*)buffer_queue.get()); +#endif -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + producer->setBufferCount(5); +#else + buffer_queue->setBufferCount(5); @@ -3469,7 +3515,7 @@ + +private: + static sp decoding_service; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + sp producer; + sp consumer; +#else @@ -4415,7 +4461,7 @@ +#endif --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_codec_layer.cpp -@@ -0,0 +1,935 @@ +@@ -0,0 +1,937 @@ +/* + * Copyright (C) 2013 Canonical Ltd + * @@ -4460,7 +4506,9 @@ +#include +#include +#include ++#if ANDROID_VERSION_MAJOR<=5 +#include ++#endif + +#include +#include @@ -5416,7 +5464,7 @@ +const char *media_codec_list_get_codec_name(size_t index) +{ + REPORT_FUNCTION() -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + return MediaCodecList::getInstance()->getCodecInfo(index)->getCodecName(); +#else + return MediaCodecList::getInstance()->getCodecName(index); @@ -5426,7 +5474,7 @@ +bool media_codec_list_is_encoder(size_t index) +{ + REPORT_FUNCTION() -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + return MediaCodecList::getInstance()->getCodecInfo(index)->isEncoder(); +#else + return MediaCodecList::getInstance()->isEncoder(index); @@ -5438,7 +5486,7 @@ + REPORT_FUNCTION() + + Vector types; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + MediaCodecList::getInstance()->getCodecInfo(index)->getSupportedMimes(&types); +#else + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); @@ -5458,7 +5506,7 @@ + REPORT_FUNCTION() + + Vector types; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + MediaCodecList::getInstance()->getCodecInfo(index)->getSupportedMimes(&types); +#else + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); @@ -5478,7 +5526,7 @@ + } + + Vector types; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + MediaCodecList::getInstance()->getCodecInfo(index)->getSupportedMimes(&types); +#else + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); @@ -5486,7 +5534,7 @@ + for (size_t i=0; i=5 + return OK; +#else + return err; @@ -5497,14 +5545,14 @@ +{ + REPORT_FUNCTION() + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + Vector profile_levels; +#else + Vector profile_levels; +#endif + Vector color_formats; + ALOGD("index: %d, type: '%s'", index, type); -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedProfileLevels(&profile_levels); + MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedColorFormats(&color_formats); +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 @@ -5569,13 +5617,13 @@ + return BAD_VALUE; + } + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + Vector profile_levels; +#else + Vector profile_levels; +#endif + Vector formats; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedProfileLevels(&profile_levels); +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats); @@ -5594,7 +5642,7 @@ + pro_level->profile = profile_levels[n].mProfile; + pro_level->level = profile_levels[n].mLevel; + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + return OK; +#else + return err; @@ -5605,13 +5653,13 @@ +{ + REPORT_FUNCTION() + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + Vector profile_levels; +#else + Vector profile_levels; +#endif + Vector formats; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedColorFormats(&formats); +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats); @@ -5637,7 +5685,7 @@ +} --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_codec_source_layer.cpp -@@ -0,0 +1,359 @@ +@@ -0,0 +1,363 @@ +/* + * Copyright (C) 2016 Canonical Ltd + * @@ -5894,8 +5942,12 @@ + MediaMessagePrivate *dm = MediaMessagePrivate::toPrivate(format); + + ALOGV("Creating media codec source"); -+ ++#if ANDROID_VERSION_MAJOR>=6 ++ // We don't use persistent input surface ++ d->codec = android::MediaCodecSource::Create(d->looper, dm->msg, d->source, NULL, flags); ++#else + d->codec = android::MediaCodecSource::Create(d->looper, dm->msg, d->source, flags); ++#endif + + return d; +} @@ -6089,7 +6141,7 @@ + } + + // From android::GLConsumer/SurfaceTexture::FrameAvailableListener -+#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 + virtual void onFrameAvailable(const android::BufferItem& item) +#else + virtual void onFrameAvailable() @@ -6244,7 +6296,7 @@ + source_fd = -1; + } + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + android::status_t setVideoSurfaceTexture(android::sp bq, const android::sp &surfaceTexture) +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 + android::status_t setVideoSurfaceTexture(const android::sp &surfaceTexture) @@ -6494,7 +6546,7 @@ + new android::NativeBufferAlloc() + ); + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + android::sp producer; + android::sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); @@ -6510,7 +6562,7 @@ + + static const bool allow_synchronous_mode = true; + // Create a new GLConsumer/SurfaceTexture from the texture_id in synchronous mode (don't wait on all data in the buffer) -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + mp->setVideoSurfaceTexture(producer, android::sp( + new android::GLConsumer( +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 @@ -6520,7 +6572,7 @@ + mp->setVideoSurfaceTexture(buffer_queue, android::sp( + new android::GLConsumer( +#endif -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + consumer, + texture_id, + GL_TEXTURE_EXTERNAL_OES, @@ -7640,7 +7692,7 @@ +#endif --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder.cpp -@@ -0,0 +1,747 @@ +@@ -0,0 +1,748 @@ +/* + ** Copyright (c) 2008 The Android Open Source Project + ** Copyright (C) 2014 Canonical Ltd @@ -7905,7 +7957,7 @@ + mIsAudioEncoderSet = true; + return ret; +} -+ ++#if ANDROID_VERSION_MAJOR<=5 +status_t MediaRecorder::setOutputFile(const char* path) +{ + ALOGV("setOutputFile(%s)", path); @@ -7931,6 +7983,7 @@ + mIsOutputFileSet = true; + return ret; +} ++#endif + +status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) +{ @@ -8390,7 +8443,7 @@ +} // namespace android --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder.h -@@ -0,0 +1,269 @@ +@@ -0,0 +1,271 @@ +/* + ** Copyright (C) 2008 The Android Open Source Project + ** Copyright (C) 2014 Canonical Ltd @@ -8614,7 +8667,9 @@ + status_t setOutputFormat(int of); + status_t setVideoEncoder(int ve); + status_t setAudioEncoder(int ae); ++#if ANDROID_VERSION_MAJOR<=5 + status_t setOutputFile(const char* path); ++#endif + status_t setOutputFile(int fd, int64_t offset, int64_t length); + status_t setVideoSize(int width, int height); + status_t setVideoFrameRate(int frames_per_second); @@ -8662,7 +8717,7 @@ +#endif // ANDROID_MEDIARECORDER_H --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_client.cpp -@@ -0,0 +1,346 @@ +@@ -0,0 +1,365 @@ +/* + * Copyright (C) 2013-2014 Canonical Ltd + * @@ -8703,7 +8758,13 @@ + + media_recorder_observer = new BpMediaRecorderObserver(service); + ++#if ANDROID_VERSION_MAJOR>=6 ++ // TODO: do we need to get valid package here? ++ const String16 opPackageName("ubuntu"); ++ recorder = new android::StagefrightRecorder(opPackageName); ++#else + recorder = new android::StagefrightRecorder; ++#endif +} + +MediaRecorderClient::~MediaRecorderClient() @@ -8790,6 +8851,7 @@ + return recorder->setAudioEncoder((android::audio_encoder)ae); +} + ++#if ANDROID_VERSION_MAJOR<=5 +status_t MediaRecorderClient::setOutputFile(const char* path) +{ + REPORT_FUNCTION(); @@ -8800,6 +8862,18 @@ + } + return recorder->setOutputFile(path); +} ++#else ++status_t MediaRecorderClient::setInputSurface(const sp& surface) ++{ ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setInputSurface(surface); ++} ++#endif + +status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length) +{ @@ -9011,7 +9085,7 @@ +} --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_client.h -@@ -0,0 +1,84 @@ +@@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013-2014 Canonical Ltd + * @@ -9063,7 +9137,11 @@ + virtual status_t setOutputFormat(int of); + virtual status_t setVideoEncoder(int ve); + virtual status_t setAudioEncoder(int ae); ++#if ANDROID_VERSION_MAJOR<=5 + virtual status_t setOutputFile(const char* path); ++#else ++ virtual status_t setInputSurface(const sp& surface); ++#endif + virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSize(int width, int height); + virtual status_t setVideoFrameRate(int frames_per_second); @@ -9098,7 +9176,7 @@ +#endif --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_factory.cpp -@@ -0,0 +1,133 @@ +@@ -0,0 +1,138 @@ +/* + * Copyright (C) 2014 Canonical Ltd + * @@ -9170,7 +9248,12 @@ + case CREATE_MEDIA_RECORDER: { + CHECK_INTERFACE(IMediaRecorderFactory, data, reply); + sp recorder = createMediaRecorder(); ++#if ANDROID_VERSION_MAJOR>=6 ++ reply->writeStrongBinder(IInterface::asBinder(recorder)); ++#else + reply->writeStrongBinder(recorder->asBinder()); ++#endif ++ + return NO_ERROR; + } break; + default: @@ -10119,7 +10202,7 @@ +} +#endif + -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 +_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) + : Surface::Surface(st, true), + refcount(1), @@ -10269,7 +10352,7 @@ + ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0."); + return NULL; + } -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); @@ -10293,7 +10376,7 @@ + stch->surface_texture.clear(); + + const bool allow_synchronous_mode = true; -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + stch->surface_texture = new GLConsumer(consumer, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); +#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 + stch->surface_texture = new SurfaceTexture(texture_id, allow_synchronous_mode, GL_TEXTURE_EXTERNAL_OES, true, buffer_queue); @@ -10609,7 +10692,7 @@ + { + } + -+#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 + virtual void onFrameAvailable(const android::BufferItem& item) +#else + virtual void onFrameAvailable() @@ -10665,19 +10748,23 @@ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris -@@ -8,6 +9,7 @@ LOCAL_SRC_FILES:= \ +@@ -8,6 +9,9 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE:= libsf_compat_layer LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include -@@ -30,6 +32,7 @@ LOCAL_SRC_FILES:= \ +@@ -30,6 +34,9 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE:= direct_sf_test LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include @@ -10687,7 +10774,7 @@ #include #include #include -+#if ANDROID_VERSION_MAJOR==5 ++#if ANDROID_VERSION_MAJOR>=5 + #include +#endif @@ -10699,7 +10786,7 @@ +#if ANDROID_VERSION_MAJOR<=4 android::SurfaceComposerClient::blankDisplay(display); -+#elif ANDROID_VERSION_MAJOR==5 ++#elif ANDROID_VERSION_MAJOR>=5 + android::SurfaceComposerClient::setDisplayPowerMode(display, HWC_POWER_MODE_OFF); +#endif } @@ -10711,7 +10798,7 @@ +#if ANDROID_VERSION_MAJOR<=4 android::SurfaceComposerClient::unblankDisplay(display); -+#elif ANDROID_VERSION_MAJOR==5 ++#elif ANDROID_VERSION_MAJOR>=5 + android::SurfaceComposerClient::setDisplayPowerMode(display, HWC_POWER_MODE_NORMAL); +#endif } @@ -10726,11 +10813,13 @@ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris -@@ -8,6 +9,7 @@ LOCAL_SRC_FILES:= \ +@@ -8,6 +9,9 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE:= libui_compat_layer LOCAL_MODULE_TAGS := optional -+LOCAL_32_BIT_ONLY := true ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include \ @@ -10763,6 +10852,21 @@ if HAS_LIBNFC_NXP_HEADERS SUBDIRS += libnfc_nxp libnfc_ndef_nxp +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/README ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/README +@@ -0,0 +1,12 @@ ++libhybris ++========= ++ ++Hybris is a solution that commits hybris, by allowing us to use bionic ++-based HW adaptations in glibc systems. ++ ++ ++Supported Architectures ++----------------------- ++ ++Libhybris currently only supports 32 bit ARM and x86 systems. 64 bit ++system are not yet supported. --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/camera/camera.c +++ libhybris-0.1.0+git20151016+6d424c9/hybris/camera/camera.c @@ -1,5 +1,5 @@ @@ -10772,7 +10876,13 @@ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. -@@ -31,8 +31,11 @@ +@@ -26,13 +26,16 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libcamera_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libcamera_compat_layer.so" + HYBRIS_LIBRARY_INITIALIZE(camera, COMPAT_LIBRARY_PATH); HYBRIS_IMPLEMENT_FUNCTION0(camera, int, android_camera_get_number_of_devices); @@ -10859,16 +10969,78 @@ + struct CameraControl*, PreviewCallbackMode); --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/Makefile.am +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/Makefile.am -@@ -36,6 +36,9 @@ endif - if WANT_DEBUG - libhybris_common_la_CFLAGS += -ggdb -O0 +@@ -1,44 +1,51 @@ + lib_LTLIBRARIES = \ + libhybris-common.la + +-# JB linker works fine for ICS +-if HAS_ANDROID_4_0_0 +-SUBDIRS = jb +-libhybris_common_la_LIBADD= jb/libandroid-linker.la +-else +-if HAS_ANDROID_5_0_0 +-SUBDIRS = jb +-libhybris_common_la_LIBADD= jb/libandroid-linker.la +-else +-if HAS_ANDROID_2_3_0 +-SUBDIRS = gingerbread +-libhybris_common_la_LIBADD= gingerbread/libandroid-linker.la +-else +-$(error No Android Version is defined) +-endif ++SUBDIRS = ++ ++if !WANT_ARCH_ARM64 ++SUBDIRS += jb + endif ++ ++if WANT_EXPERIMENTAL ++SUBDIRS += mm + endif + + libhybris_common_la_SOURCES = \ + hooks.c \ + hooks_shm.c \ + strlcpy.c \ +- dlfcn.c \ ++ strlcat.c \ + logging.c \ + sysconf.c +-libhybris_common_la_CFLAGS = \ ++libhybris_common_la_CPPFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ +- -I$(top_srcdir)/common ++ -I$(top_srcdir)/common \ ++ -DLINKER_PLUGIN_DIR=\"$(libdir)/libhybris/linker\" + if WANT_TRACE +-libhybris_common_la_CFLAGS += -DDEBUG ++libhybris_common_la_CPPFLAGS += -DDEBUG endif + if WANT_DEBUG +-libhybris_common_la_CFLAGS += -ggdb -O0 ++libhybris_common_la_CPPFLAGS += -ggdb -O0 ++endif +if WANT_MALI_QUIRKS -+libhybris_common_la_CFLAGS += -DMALI_QUIRKS ++libhybris_common_la_CPPFLAGS += -DMALI_QUIRKS +endif ++if WANT_UBUNTU_LINKER_OVERRIDES ++libhybris_common_la_CPPFLAGS += -DUBUNTU_LINKER_OVERRIDES ++endif ++if !WANT_ARCH_ARM64 ++libhybris_common_la_CPPFLAGS += -DWANT_LINKER_JB ++endif ++if WANT_EXPERIMENTAL ++libhybris_common_la_CPPFLAGS += -DWANT_LINKER_MM + endif libhybris_common_la_LDFLAGS = \ -ldl \ -lrt \ + -pthread \ ++ -lc \ ++ -lstdc++ \ + $(top_builddir)/properties/libandroid-properties.la \ + -version-info "$(LT_CURRENT)":"$(LT_REVISION)":"$(LT_AGE)" --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks.c +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks.c @@ -27,6 +27,7 @@ @@ -10879,7 +11051,18 @@ #include #include #include -@@ -44,12 +45,17 @@ +@@ -39,22 +40,47 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include + + #include #include #include @@ -10894,10 +11077,29 @@ #include #include +#include ++ ++#include ++#include ++#include #include ++#include -@@ -68,8 +74,12 @@ static int locale_inited = 0; + static locale_t hybris_locale; + static int locale_inited = 0; ++static hybris_hook_cb hook_callback = NULL; ++ ++static void (*_android_linker_init)(int sdk_version, void* (*get_hooked_symbol)(const char*, const char*)) = NULL; ++static void* (*_android_dlopen)(const char *filename, int flags) = NULL; ++static void* (*_android_dlsym)(void *handle, const char *symbol) = NULL; ++static void* (*_android_dladdr)(void *addr, Dl_info *info) = NULL; ++static int (*_android_dlclose)(void *handle) = NULL; ++static const char* (*_android_dlerror)(void) = NULL; ++ + /* 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) +@@ -68,8 +94,12 @@ static int locale_inited = 0; #define ANDROID_MUTEX_SHARED_MASK 0x2000 #define ANDROID_COND_SHARED_MASK 0x0001 @@ -10910,7 +11112,7 @@ /* For the static initializer types */ #define ANDROID_PTHREAD_MUTEX_INITIALIZER 0 #define ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER 0x4000 -@@ -77,6 +87,8 @@ static int locale_inited = 0; +@@ -77,10 +107,21 @@ static int locale_inited = 0; #define ANDROID_PTHREAD_COND_INITIALIZER 0 #define ANDROID_PTHREAD_RWLOCK_INITIALIZER 0 @@ -10919,7 +11121,20 @@ /* Debug */ #include "logging.h" #define LOGD(message, ...) HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__) -@@ -91,6 +103,11 @@ struct _hook { + ++#ifdef DEBUG ++#define TRACE_HOOK(message, ...) \ ++ if (hybris_should_trace(NULL, NULL)) { \ ++ HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__); \ ++ } ++#else ++#define TRACE_HOOK(message, ...) ++#endif ++ + /* we have a value p: + * - if p <= ANDROID_TOP_ADDR_VALUE_MUTEX then it is an android mutex, not one we processed + * - if p > VMALLOC_END, then the pointer is not a result of malloc ==> it is an shm offset +@@ -91,6 +132,11 @@ struct _hook { void *func; }; @@ -10931,7 +11146,7 @@ /* Helpers */ static int hybris_check_android_shared_mutex(unsigned int mutex_addr) { -@@ -113,9 +130,59 @@ static int hybris_check_android_shared_c +@@ -113,9 +159,59 @@ static int hybris_check_android_shared_c (cond_addr & ANDROID_COND_SHARED_MASK)) return 1; @@ -10991,1078 +11206,14037 @@ static void hybris_set_mutex_attr(unsigned int android_value, pthread_mutexattr_t *attr) { /* Init already sets as PTHREAD_MUTEX_NORMAL */ -@@ -178,7 +245,6 @@ static void *my_memcpy(void *dst, const +@@ -159,25 +255,49 @@ static pthread_rwlock_t* hybris_alloc_in + * utils, such as malloc, memcpy + * + * Useful to handle hacks such as the one applied for Nvidia, and to +- * avoid crashes. ++ * avoid crashes. Also we need to hook all memory allocation related ++ * ones to make sure all are using the same allocator implementation. + * + * */ - static size_t my_strlen(const char *s) +-static void *my_malloc(size_t size) ++static void *_hybris_hook_malloc(size_t size) ++{ ++ TRACE_HOOK("size %u", size); ++ ++ void *res = malloc(size); ++ ++ TRACE_HOOK("res %p", res); ++ ++ return res; ++} ++ ++static size_t _hybris_hook_malloc_usable_size (void *ptr) { -- +- return malloc(size); ++ TRACE_HOOK("ptr %p", ptr); ++ ++ return malloc_usable_size(ptr); + } + +-static void *my_memcpy(void *dst, const void *src, size_t len) ++static void *_hybris_hook_memcpy(void *dst, const void *src, size_t len) + { ++ TRACE_HOOK("dst %p src %p len %u", dst, src, len); ++ + if (src == NULL || dst == NULL) + return NULL; + + return memcpy(dst, src, len); + } + +-static size_t my_strlen(const char *s) ++static int _hybris_hook_memcmp(const void *s1, const void *s2, size_t n) ++{ ++ TRACE_HOOK("s1 %p '%s' s2 %p '%s' n %u", s1, (char*) s1, s2, (char*) s2, n); ++ ++ return memcmp(s1, s2, n); ++} ++ ++static size_t _hybris_hook_strlen(const char *s) + { ++ TRACE_HOOK("s '%s'", s); + if (s == NULL) return -1; +@@ -185,9 +305,11 @@ static size_t my_strlen(const char *s) + return strlen(s); + } -@@ -187,7 +253,7 @@ static size_t my_strlen(const char *s) - - static pid_t my_gettid( void ) +-static pid_t my_gettid( void ) ++static pid_t _hybris_hook_gettid(void) { - return syscall( __NR_gettid ); ++ TRACE_HOOK(""); ++ + return syscall(__NR_gettid); } /* -@@ -209,6 +275,14 @@ static int my_pthread_create(pthread_t * +@@ -198,17 +320,43 @@ static pid_t my_gettid( void ) + * + * */ + +-static int my_pthread_create(pthread_t *thread, const pthread_attr_t *__attr, ++static int _hybris_hook_pthread_create(pthread_t *thread, const pthread_attr_t *__attr, + void *(*start_routine)(void*), void *arg) + { + pthread_attr_t *realattr = NULL; + ++ TRACE_HOOK("thread %p attr %p", thread, __attr); ++ + if (__attr != NULL) + realattr = (pthread_attr_t *) *(unsigned int *) __attr; + return pthread_create(thread, realattr, start_routine, arg); } -+static int my_pthread_kill(pthread_t thread, int sig) ++static int _hybris_hook_pthread_kill(pthread_t thread, int sig) +{ ++ TRACE_HOOK("thread %llu sig %d", (unsigned long long) thread, sig); ++ + if (thread == 0) + return ESRCH; + + return pthread_kill(thread, sig); +} + - /* - * pthread_attr_* functions - * -@@ -515,6 +589,29 @@ static int my_pthread_mutex_lock_timeout - return pthread_mutex_timedlock(realmutex, &tv); - } - -+static int my_pthread_mutex_timedlock(pthread_mutex_t *__mutex, -+ const struct timespec *__abs_timeout) ++static int _hybris_hook_pthread_setspecific(pthread_key_t key, const void *ptr) +{ -+ if (!__mutex) { -+ LOGD("Null mutex lock, not unlocking."); -+ return 0; -+ } ++ TRACE_HOOK("key %d ptr %d", key, ptr); + -+ unsigned int value = (*(unsigned int *) __mutex); -+ if (hybris_check_android_shared_mutex(value)) { -+ LOGD("Shared mutex with Android, not lock timeout np."); -+ return 0; -+ } ++ return pthread_setspecific(key, ptr); ++} + -+ pthread_mutex_t *realmutex = (pthread_mutex_t *) value; -+ if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) { -+ realmutex = hybris_alloc_init_mutex(value); -+ *((int *)__mutex) = (int) realmutex; -+ } ++static void* _hybris_hook_pthread_getspecific(pthread_key_t key) ++{ ++ TRACE_HOOK("key %d", key); + -+ return pthread_mutex_timedlock(realmutex, __abs_timeout); ++ return pthread_getspecific(key); +} + - static int my_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, - int pshared) - { -@@ -585,8 +682,8 @@ static int my_pthread_cond_broadcast(pth - { - unsigned int value = (*(unsigned int *) cond); - if (hybris_check_android_shared_cond(value)) { -- LOGD("shared condition with Android, not broadcasting."); -- return 0; -+ LOGD("Shared condition with Android, broadcasting with futex."); -+ return android_pthread_cond_broadcast((android_cond_t *) cond); - } + /* + * pthread_attr_* functions + * +@@ -217,124 +365,177 @@ static int my_pthread_create(pthread_t * + * + * */ - pthread_cond_t *realcond = (pthread_cond_t *) value; -@@ -606,8 +703,8 @@ static int my_pthread_cond_signal(pthrea - unsigned int value = (*(unsigned int *) cond); +-static int my_pthread_attr_init(pthread_attr_t *__attr) ++static int _hybris_hook_pthread_attr_init(pthread_attr_t *__attr) + { + pthread_attr_t *realattr; - if (hybris_check_android_shared_cond(value)) { -- LOGD("Shared condition with Android, not signaling."); -- return 0; -+ LOGD("Shared condition with Android, broadcasting with futex."); -+ return android_pthread_cond_signal((android_cond_t *) cond); - } ++ TRACE_HOOK("attr %p", __attr); ++ + realattr = malloc(sizeof(pthread_attr_t)); + *((unsigned int *)__attr) = (unsigned int) realattr; - pthread_cond_t *realcond = (pthread_cond_t *) value; -@@ -731,6 +828,28 @@ static int my_pthread_cond_timedwait_rel - return pthread_cond_timedwait(realcond, realmutex, &tv); + return pthread_attr_init(realattr); } -+int my_pthread_setname_np(pthread_t thread, const char *name) -+{ -+#ifdef MALI_QUIRKS -+ if (strcmp(name, MALI_HIST_DUMP_THREAD_NAME) == 0) { -+ HYBRIS_DEBUG_LOG(HOOKS, "%s: Found mali-hist-dump thread, killing it ...", -+ __FUNCTION__); +-static int my_pthread_attr_destroy(pthread_attr_t *__attr) ++static int _hybris_hook_pthread_attr_destroy(pthread_attr_t *__attr) + { + int ret; + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + ++ TRACE_HOOK("attr %p", __attr); + -+ if (thread != pthread_self()) { -+ HYBRIS_DEBUG_LOG(HOOKS, "%s: -> Failed, as calling thread is not mali-hist-dump itself", -+ __FUNCTION__); -+ return; -+ } + ret = pthread_attr_destroy(realattr); +- /* We need to release the memory allocated at my_pthread_attr_init ++ /* We need to release the memory allocated at _hybris_hook_pthread_attr_init + * Possible side effects if destroy is called without our init */ + free(realattr); + + return ret; + } + +-static int my_pthread_attr_setdetachstate(pthread_attr_t *__attr, int state) ++static int _hybris_hook_pthread_attr_setdetachstate(pthread_attr_t *__attr, int state) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ pthread_exit(thread); ++ TRACE_HOOK("attr %p state %d", __attr, state); + -+ return; -+ } -+#endif + return pthread_attr_setdetachstate(realattr, state); + } + +-static int my_pthread_attr_getdetachstate(pthread_attr_t const *__attr, int *state) ++static int _hybris_hook_pthread_attr_getdetachstate(pthread_attr_t const *__attr, int *state) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ return pthread_setname_np(thread, name); -+} ++ TRACE_HOOK("attr %p state %p", __attr, state); + - /* - * pthread_rwlockattr_* functions - * -@@ -898,6 +1017,18 @@ static int my_pthread_rwlock_unlock(pthr - return pthread_rwlock_unlock(realrwlock); + return pthread_attr_getdetachstate(realattr, state); } -+#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) +-static int my_pthread_attr_setschedpolicy(pthread_attr_t *__attr, int policy) ++static int _hybris_hook_pthread_attr_setschedpolicy(pthread_attr_t *__attr, int policy) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+static pid_t my_pthread_gettid(pthread_t t) -+{ -+ // glibc doesn't offer us a way to retrieve the thread id for a -+ // specific thread. However pthread_t is defined as unsigned -+ // long int and is the thread id so we can just copy it over -+ // into a pid_t. -+ pid_t tid; -+ memcpy(&tid, &t, min(sizeof(tid), sizeof(t))); -+ return tid; -+} ++ TRACE_HOOK("attr %p policy %d", __attr, policy); ++ + return pthread_attr_setschedpolicy(realattr, policy); + } - static int my_set_errno(int oi_errno) +-static int my_pthread_attr_getschedpolicy(pthread_attr_t const *__attr, int *policy) ++static int _hybris_hook_pthread_attr_getschedpolicy(pthread_attr_t const *__attr, int *policy) { -@@ -1255,6 +1386,41 @@ static int my_readdir_r(DIR *dir, struct - return res; + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p policy %p", __attr, policy); ++ + return pthread_attr_getschedpolicy(realattr, policy); } -+static inline void swap(void **a, void **b) -+{ -+ void *tmp = *a; -+ *a = *b; -+ *b = tmp; -+} -+ -+static int my_getaddrinfo(const char *hostname, const char *servname, -+ const struct addrinfo *hints, struct addrinfo **res) -+{ -+ // make a local copy of hints -+ struct addrinfo *fixed_hints = (struct addrinfo*)malloc(sizeof(struct addrinfo)); -+ memcpy(fixed_hints, hints, sizeof(struct addrinfo)); -+ // fix bionic -> glibc missmatch -+ swap((void**)&(fixed_hints->ai_canonname), (void**)&(fixed_hints->ai_addr)); -+ // do glibc getaddrinfo -+ int result = getaddrinfo(hostname, servname, fixed_hints, res); -+ // release the copy of hints -+ free(fixed_hints); -+ // fix bionic <- glibc missmatch -+ struct addrinfo *it = *res; -+ while(NULL != it) -+ { -+ swap((void**)&(it->ai_canonname), (void**)&(it->ai_addr)); -+ it = it->ai_next; -+ } -+ return result; -+} +-static int my_pthread_attr_setschedparam(pthread_attr_t *__attr, struct sched_param const *param) ++static int _hybris_hook_pthread_attr_setschedparam(pthread_attr_t *__attr, struct sched_param const *param) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+static void my_freeaddrinfo(struct addrinfo *__ai) -+{ -+ swap((void**)&(__ai->ai_canonname), (void**)&(__ai->ai_addr)); -+ freeaddrinfo(__ai); -+} ++ TRACE_HOOK("attr %p param %p", __attr, param); + - extern long my_sysconf(int name); - - FP_ATTRIB static double my_strtod(const char *nptr, char **endptr) -@@ -1267,6 +1433,51 @@ FP_ATTRIB static double my_strtod(const - return strtod_l(nptr, endptr, hybris_locale); + return pthread_attr_setschedparam(realattr, param); } -+static int __my_system_property_read(const void *pi, char *name, char *value) -+{ -+ return property_get(name, value, NULL); -+} -+ -+static int __my_system_property_foreach(void (*propfn)(const void *pi, void *cookie), void *cookie) -+{ -+ return 0; -+} +-static int my_pthread_attr_getschedparam(pthread_attr_t const *__attr, struct sched_param *param) ++static int _hybris_hook_pthread_attr_getschedparam(pthread_attr_t const *__attr, struct sched_param *param) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+static const void *__my_system_property_find(const char *name) -+{ -+ return NULL; -+} ++ TRACE_HOOK("attr %p param %p", __attr, param); + -+static unsigned int __my_system_property_serial(const void *pi) -+{ -+ return 0; -+} + return pthread_attr_getschedparam(realattr, param); + } + +-static int my_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stack_size) ++static int _hybris_hook_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+static int __my_system_property_wait(const void *pi) -+{ -+ return 0; -+} ++ TRACE_HOOK("attr %p stack size %u", __attr, stack_size); + -+static int __my_system_property_update(void *pi, const char *value, unsigned int len) -+{ -+ return 0; -+} + return pthread_attr_setstacksize(realattr, stack_size); + } + +-static int my_pthread_attr_getstacksize(pthread_attr_t const *__attr, size_t *stack_size) ++static int _hybris_hook_pthread_attr_getstacksize(pthread_attr_t const *__attr, size_t *stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+static int __my_system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen) -+{ -+ return 0; -+} ++ TRACE_HOOK("attr %p stack size %p", __attr, stack_size); + -+static unsigned int __my_system_property_wait_any(unsigned int serial) -+{ -+ return 0; -+} + return pthread_attr_getstacksize(realattr, stack_size); + } + +-static int my_pthread_attr_setstackaddr(pthread_attr_t *__attr, void *stack_addr) ++static int _hybris_hook_pthread_attr_setstackaddr(pthread_attr_t *__attr, void *stack_addr) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+static const void *__my_system_property_find_nth(unsigned n) -+{ -+ return NULL; -+} ++ TRACE_HOOK("attr %p stack addr %p", __attr, stack_addr); + - extern int __cxa_atexit(void (*)(void*), void*, void*); - extern void __cxa_finalize(void * d); - -@@ -1276,10 +1487,10 @@ struct open_redirect { - }; - - struct open_redirect open_redirects[] = { -- { "/dev/log/main", "/dev/log_main" }, -- { "/dev/log/radio", "/dev/log_radio" }, -- { "/dev/log/system", "/dev/log_system" }, -- { "/dev/log/events", "/dev/log_events" }, -+ { "/dev/log/main", "/dev/alog/main" }, -+ { "/dev/log/radio", "/dev/alog/radio" }, -+ { "/dev/log/system", "/dev/alog/system" }, -+ { "/dev/log/events", "/dev/alog/events" }, - { NULL, NULL } - }; - -@@ -1329,6 +1540,30 @@ void *__get_tls_hooks() - return tls_hooks; + return pthread_attr_setstackaddr(realattr, stack_addr); } -+int my_prctl(int option, unsigned long arg2, unsigned long arg3, -+ unsigned long arg4, unsigned long arg5) -+{ -+#ifdef MALI_QUIRKS -+ if (option == PR_SET_NAME) { -+ char *name = (char*) arg2; +-static int my_pthread_attr_getstackaddr(pthread_attr_t const *__attr, void **stack_addr) ++static int _hybris_hook_pthread_attr_getstackaddr(pthread_attr_t const *__attr, void **stack_addr) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ if (strcmp(name, MALI_HIST_DUMP_THREAD_NAME) == 0) { ++ TRACE_HOOK("attr %p stack addr %p", __attr, stack_addr); + -+ // This can only work because prctl with PR_SET_NAME -+ // can be only called for the current thread and not -+ // for another thread so we can safely pause things. + return pthread_attr_getstackaddr(realattr, stack_addr); + } + +-static int my_pthread_attr_setstack(pthread_attr_t *__attr, void *stack_base, size_t stack_size) ++static int _hybris_hook_pthread_attr_setstack(pthread_attr_t *__attr, void *stack_base, size_t stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ HYBRIS_DEBUG_LOG(HOOKS, "%s: Found mali-hist-dump, killing thread ...", -+ __FUNCTION__); ++ TRACE_HOOK("attr %p stack base %p stack size %u", __attr, ++ stack_base, stack_size); + -+ pthread_exit(NULL); -+ } -+ } -+#endif + return pthread_attr_setstack(realattr, stack_base, stack_size); + } + +-static int my_pthread_attr_getstack(pthread_attr_t const *__attr, void **stack_base, size_t *stack_size) ++static int _hybris_hook_pthread_attr_getstack(pthread_attr_t const *__attr, void **stack_base, size_t *stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ return prctl(option, arg2, arg3, arg4, arg5); -+} ++ TRACE_HOOK("attr %p stack base %p stack size %p", __attr, ++ stack_base, stack_size); + - static struct _hook hooks[] = { - {"property_get", property_get }, - {"property_set", property_set }, -@@ -1354,6 +1589,7 @@ static struct _hook hooks[] = { - {"memmove",memmove}, - {"memset",memset}, - {"memmem",memmem}, -+ {"getlogin", getlogin}, - // {"memswap",memswap}, - {"index",index}, - {"rindex",rindex}, -@@ -1395,6 +1631,8 @@ static struct _hook hooks[] = { - {"index",index}, - {"rindex",rindex}, - {"strcasecmp",strcasecmp}, -+ {"__sprintf_chk", __sprintf_chk}, -+ {"__snprintf_chk", __snprintf_chk}, - {"strncasecmp",strncasecmp}, - /* dirent.h */ - {"opendir", opendir}, -@@ -1405,7 +1643,7 @@ static struct _hook hooks[] = { - {"getpid", getpid}, - {"pthread_atfork", pthread_atfork}, - {"pthread_create", my_pthread_create}, -- {"pthread_kill", pthread_kill}, -+ {"pthread_kill", my_pthread_kill}, - {"pthread_exit", pthread_exit}, - {"pthread_join", pthread_join}, - {"pthread_detach", pthread_detach}, -@@ -1419,6 +1657,7 @@ static struct _hook hooks[] = { - {"pthread_mutex_unlock", my_pthread_mutex_unlock}, - {"pthread_mutex_trylock", my_pthread_mutex_trylock}, - {"pthread_mutex_lock_timeout_np", my_pthread_mutex_lock_timeout_np}, -+ {"pthread_mutex_timedlock", my_pthread_mutex_timedlock}, - {"pthread_mutexattr_init", pthread_mutexattr_init}, - {"pthread_mutexattr_destroy", pthread_mutexattr_destroy}, - {"pthread_mutexattr_gettype", pthread_mutexattr_gettype}, -@@ -1429,6 +1668,8 @@ static struct _hook hooks[] = { - {"pthread_condattr_getpshared", pthread_condattr_getpshared}, - {"pthread_condattr_setpshared", pthread_condattr_setpshared}, - {"pthread_condattr_destroy", pthread_condattr_destroy}, -+ {"pthread_condattr_getclock", pthread_condattr_getclock}, -+ {"pthread_condattr_setclock", pthread_condattr_setclock}, - {"pthread_cond_init", my_pthread_cond_init}, - {"pthread_cond_destroy", my_pthread_cond_destroy}, - {"pthread_cond_broadcast", my_pthread_cond_broadcast}, -@@ -1439,7 +1680,7 @@ static struct _hook hooks[] = { - {"pthread_cond_timedwait_monotonic_np", my_pthread_cond_timedwait}, - {"pthread_cond_timedwait_relative_np", my_pthread_cond_timedwait_relative_np}, - {"pthread_key_delete", pthread_key_delete}, -- {"pthread_setname_np", pthread_setname_np}, -+ {"pthread_setname_np", my_pthread_setname_np}, - {"pthread_once", pthread_once}, - {"pthread_key_create", pthread_key_create}, - {"pthread_setspecific", pthread_setspecific}, -@@ -1461,7 +1702,7 @@ static struct _hook hooks[] = { - {"pthread_attr_setguardsize", my_pthread_attr_setguardsize}, - {"pthread_attr_getguardsize", my_pthread_attr_getguardsize}, - {"pthread_attr_setscope", my_pthread_attr_setscope}, -- {"pthread_attr_setscope", my_pthread_attr_getscope}, -+ {"pthread_attr_getscope", my_pthread_attr_getscope}, - {"pthread_getattr_np", my_pthread_getattr_np}, - {"pthread_rwlockattr_init", my_pthread_rwlockattr_init}, - {"pthread_rwlockattr_destroy", my_pthread_rwlockattr_destroy}, -@@ -1476,6 +1717,9 @@ static struct _hook hooks[] = { - {"pthread_rwlock_trywrlock", my_pthread_rwlock_trywrlock}, - {"pthread_rwlock_timedrdlock", my_pthread_rwlock_timedrdlock}, - {"pthread_rwlock_timedwrlock", my_pthread_rwlock_timedwrlock}, -+ /* bionic-only pthread */ -+ {"__pthread_gettid", my_pthread_gettid}, -+ {"pthread_gettid_np", my_pthread_gettid}, - /* stdio.h */ - {"__isthreaded", &__my_isthreaded}, - {"__sF", &my_sF}, -@@ -1536,7 +1780,8 @@ static struct _hook hooks[] = { - {"__errno", __errno_location}, - {"__set_errno", my_set_errno}, - /* net specifics, to avoid __res_get_state */ -- {"getaddrinfo", getaddrinfo}, -+ {"getaddrinfo", my_getaddrinfo}, -+ {"freeaddrinfo", my_freeaddrinfo}, - {"gethostbyaddr", gethostbyaddr}, - {"gethostbyname", gethostbyname}, - {"gethostbyname2", gethostbyname2}, -@@ -1575,6 +1820,9 @@ static struct _hook hooks[] = { - {"timer_gettime", timer_gettime}, - {"timer_delete", timer_delete}, - {"timer_getoverrun", timer_getoverrun}, -+ {"localtime", localtime}, -+ {"localtime_r", localtime_r}, -+ {"gmtime", gmtime}, - {"abort", abort}, - {"writev", writev}, - /* unistd.h */ -@@ -1583,31 +1831,64 @@ static struct _hook hooks[] = { - {"getgrgid", getgrgid}, - {"__cxa_atexit", __cxa_atexit}, - {"__cxa_finalize", __cxa_finalize}, -- {NULL, NULL}, -+ {"__system_property_read", __my_system_property_read}, -+ {"__system_property_set", property_set}, -+ {"__system_property_foreach", __my_system_property_foreach}, -+ {"__system_property_find", __my_system_property_find}, -+ {"__system_property_serial", __my_system_property_serial}, -+ {"__system_property_wait", __my_system_property_wait}, -+ {"__system_property_update", __my_system_property_update}, -+ {"__system_property_add", __my_system_property_add}, -+ {"__system_property_wait_any", __my_system_property_wait_any}, -+ {"__system_property_find_nth", __my_system_property_find_nth}, -+ /* sys/prctl.h */ -+ {"prctl", my_prctl}, - }; + return pthread_attr_getstack(realattr, stack_base, stack_size); + } -+static int hook_cmp(const void *a, const void *b) -+{ -+ return strcmp(((struct _hook*)a)->name, ((struct _hook*)b)->name); -+} -+ - void *get_hooked_symbol(char *sym) +-static int my_pthread_attr_setguardsize(pthread_attr_t *__attr, size_t guard_size) ++static int _hybris_hook_pthread_attr_setguardsize(pthread_attr_t *__attr, size_t guard_size) { -- struct _hook *ptr = &hooks[0]; - static int counter = -1; -+ static int sorted = 0; -+ const int nhooks = sizeof(hooks) / sizeof(hooks[0]); -+ void *found = NULL; -+ struct _hook key; + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p guard size %u", __attr, guard_size); ++ + return pthread_attr_setguardsize(realattr, guard_size); + } -- while (ptr->name != NULL) -+ if (!sorted) - { -- if (strcmp(sym, ptr->name) == 0){ -- return ptr->func; -- } -- ptr++; -+ qsort(hooks, nhooks, sizeof(hooks[0]), hook_cmp); -+ sorted = 1; - } -- if (strstr(sym, "pthread") != NULL) +-static int my_pthread_attr_getguardsize(pthread_attr_t const *__attr, size_t *guard_size) ++static int _hybris_hook_pthread_attr_getguardsize(pthread_attr_t const *__attr, size_t *guard_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ key.name = sym; -+ found = bsearch(&key, hooks, nhooks, sizeof(hooks[0]), hook_cmp); -+ if (found != NULL) -+ { -+ LOGD("Found hook for symbol %s", sym); -+ return ((struct _hook*)found)->func; -+ } ++ TRACE_HOOK("attr %p guard size %p", __attr, guard_size); + -+ if (strncmp(sym, "pthread", 7) == 0 || -+ strncmp(sym, "__pthread", 9) == 0) - { - /* safe */ - if (strcmp(sym, "pthread_sigmask") == 0) - return NULL; - /* not safe */ - counter--; -- LOGD("%s %i\n", sym, counter); -+ // If you're experiencing a crash later on check the address of the -+ // function pointer being call. If it matches the printed counter -+ // value here then you can easily find out which symbol is missing. -+ LOGD("Missing hook for pthread symbol %s (counter %i)\n", sym, counter); - return (void *) counter; - } + return pthread_attr_getguardsize(realattr, guard_size); + } + +-static int my_pthread_attr_setscope(pthread_attr_t *__attr, int scope) ++static int _hybris_hook_pthread_attr_setscope(pthread_attr_t *__attr, int scope) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + -+ LOGD("Could not find a hook for symbol %s", sym); ++ TRACE_HOOK("attr %p scope %d", __attr, scope); + - return NULL; + return pthread_attr_setscope(realattr, scope); } ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks_shm.c -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks_shm.c -@@ -123,7 +123,9 @@ static void _hybris_shm_init() - else { - LOGD("Creating a new shared memory segment."); +-static int my_pthread_attr_getscope(pthread_attr_t const *__attr) ++static int _hybris_hook_pthread_attr_getscope(pthread_attr_t const *__attr) + { + int scope; + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; -- _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0660); -+ mode_t pumask = umask(0); -+ _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0666); -+ umask(pumask); - if (_hybris_shm_fd >= 0) { - ftruncate( _hybris_shm_fd, size_to_map ); - /* Map the memory object */ -@@ -171,11 +173,12 @@ static void _hybris_shm_extend_region() ++ TRACE_HOOK("attr %p", __attr); ++ + /* Android doesn't have the scope attribute because it always + * returns PTHREAD_SCOPE_SYSTEM */ + pthread_attr_getscope(realattr, &scope); +@@ -342,10 +543,12 @@ static int my_pthread_attr_getscope(pthr + return scope; + } - /* - * Determine if the pointer that has been extracted by hybris is -- * pointing to an address in the shared memory -+ * pointing to an address in the shared memory. - */ - int hybris_is_pointer_in_shm(void *ptr) +-static int my_pthread_getattr_np(pthread_t thid, pthread_attr_t *__attr) ++static int _hybris_hook_pthread_getattr_np(pthread_t thid, pthread_attr_t *__attr) { -- if ((unsigned int)ptr >= HYBRIS_SHM_MASK) -+ if (((unsigned int) ptr >= HYBRIS_SHM_MASK) && -+ ((unsigned int) ptr <= HYBRIS_SHM_MASK_TOP)) - return 1; + pthread_attr_t *realattr; - return 0; ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks_shm.h -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks_shm.h -@@ -20,6 +20,9 @@ ++ TRACE_HOOK("attr %p", __attr); ++ + realattr = malloc(sizeof(pthread_attr_t)); + *((unsigned int *)__attr) = (unsigned int) realattr; - #include +@@ -360,11 +563,13 @@ static int my_pthread_getattr_np(pthread + * + * */ -+/* Leave space to workaround the issue that Android might pass negative int values */ -+#define HYBRIS_SHM_MASK_TOP 0xFFFFFFF0UL +-static int my_pthread_mutex_init(pthread_mutex_t *__mutex, ++static int _hybris_hook_pthread_mutex_init(pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) + { + pthread_mutex_t *realmutex = NULL; + ++ TRACE_HOOK("mutex %p attr %p", __mutex, __mutexattr); + - typedef unsigned int hybris_shm_pointer_t; + int pshared = 0; + if (__mutexattr) + pthread_mutexattr_getpshared(__mutexattr, &pshared); +@@ -388,10 +593,12 @@ static int my_pthread_mutex_init(pthread + return pthread_mutex_init(realmutex, __mutexattr); + } - /* ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/dlfcn.c -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/dlfcn.c -@@ -78,7 +78,7 @@ const char *android_dlerror(void) - void *android_dlsym(void *handle, const char *symbol) +-static int my_pthread_mutex_destroy(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_destroy(pthread_mutex_t *__mutex) { - soinfo *found; -- Elf32_Sym *sym; -+ Elf_Sym *sym; - unsigned bind; - - pthread_mutex_lock(&dl_lock); -@@ -142,7 +142,7 @@ int android_dladdr(const void *addr, Dl_ - info->dli_fbase = (void*)si->base; - - /* Determine if any symbol in the library contains the specified address */ -- Elf32_Sym *sym = find_containing_symbol(addr, si); -+ Elf_Sym *sym = find_containing_symbol(addr, si); - - if(sym != NULL) { - info->dli_sname = si->strtab + sym->st_name; -@@ -171,7 +171,7 @@ int android_dl_iterate_phdr(int (*cb)(st - // 0000000 00011111 111112 22222222 2333333 333344444444445555555 - // 0123456 78901234 567890 12345678 9012345 678901234567890123456 - #define ANDROID_LIBDL_STRTAB \ -- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0dl_iterate_phdr\0" -+ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0dl_unwind_find_exidx\0" + int ret; - _Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); - -@@ -191,7 +191,7 @@ _Unwind_Ptr android_dl_unwind_find_exidx - #endif ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (!__mutex) + return EINVAL; +@@ -414,8 +621,10 @@ static int my_pthread_mutex_destroy(pthr + return ret; + } --static Elf32_Sym libdl_symtab[] = { -+static Elf_Sym libdl_symtab[] = { - // total length of libdl_info.strtab, including trailing 0 - // This is actually the the STH_UNDEF entry. Technically, it's - // supposed to have st_name == 0, but instead, it points to an index -@@ -199,44 +199,42 @@ static Elf32_Sym libdl_symtab[] = { - { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, - }, - { st_name: 0, // starting index of the name in libdl_info.strtab -- st_value: (Elf32_Addr) &android_dlopen, -+ st_value: (Elf_Addr) &android_dlopen, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 7, -- st_value: (Elf32_Addr) &android_dlclose, -+ st_value: (Elf_Addr) &android_dlclose, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 15, -- st_value: (Elf32_Addr) &android_dlsym, -+ st_value: (Elf_Addr) &android_dlsym, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 21, -- st_value: (Elf32_Addr) &android_dlerror, -+ st_value: (Elf_Addr) &android_dlerror, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 29, -- st_value: (Elf32_Addr) &android_dladdr, -+ st_value: (Elf_Addr) &android_dladdr, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, --#ifdef ANDROID_ARM_LINKER - { st_name: 36, -- st_value: (Elf32_Addr) &android_dl_unwind_find_exidx, -+ st_value: (Elf_Addr) &android_dl_iterate_phdr, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -- { st_name: 57, --#else -- { st_name: 36, --#endif -- st_value: (Elf32_Addr) &android_dl_iterate_phdr, -+#ifdef ANDROID_ARM_LINKER -+ { st_name: 52, -+ st_value: (Elf_Addr) &android_dl_unwind_find_exidx, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -+#endif - }; +-static int my_pthread_mutex_lock(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_lock(pthread_mutex_t *__mutex) + { ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (!__mutex) { + LOGD("Null mutex lock, not locking."); + return 0; +@@ -432,6 +641,7 @@ static int my_pthread_mutex_lock(pthread + realmutex = (pthread_mutex_t *)hybris_get_shmpointer((hybris_shm_pointer_t)value); + + if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) { ++ TRACE("value %p <= ANDROID_TOP_ADDR_VALUE_MUTEX 0x%x", value, ANDROID_TOP_ADDR_VALUE_MUTEX); + realmutex = hybris_alloc_init_mutex(value); + *((unsigned int *)__mutex) = (unsigned int) realmutex; + } +@@ -439,10 +649,12 @@ static int my_pthread_mutex_lock(pthread + return pthread_mutex_lock(realmutex); + } - /* Fake out a hash table with a single bucket. -@@ -273,12 +271,8 @@ soinfo libdl_info = { - symtab: libdl_symtab, +-static int my_pthread_mutex_trylock(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_trylock(pthread_mutex_t *__mutex) + { + unsigned int value = (*(unsigned int *) __mutex); - refcount: 1, -- nbucket: 1, --#if defined(ANDROID_ARM_LINKER) -- nchain: 8, --#else -- nchain: 7, --#endif -+ nbucket: sizeof(libdl_buckets)/sizeof(unsigned), -+ nchain: sizeof(libdl_chains)/sizeof(unsigned), - bucket: libdl_buckets, - chain: libdl_chains, - }; ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker.c -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.c -@@ -380,10 +380,10 @@ android_dl_iterate_phdr(int (*cb)(struct - return rv; ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (hybris_check_android_shared_mutex(value)) { + LOGD("Shared mutex with Android, not try locking."); + return 0; +@@ -460,8 +672,10 @@ static int my_pthread_mutex_trylock(pthr + return pthread_mutex_trylock(realmutex); } --static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) -+static Elf_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) +-static int my_pthread_mutex_unlock(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_unlock(pthread_mutex_t *__mutex) { -- Elf32_Sym *s; -- Elf32_Sym *symtab = si->symtab; -+ Elf_Sym *s; -+ Elf_Sym *symtab = si->symtab; - const char *strtab = si->strtab; - unsigned n; - -@@ -425,11 +425,11 @@ static unsigned elfhash(const char *_nam - return h; ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (!__mutex) { + LOGD("Null mutex lock, not unlocking."); + return 0; +@@ -486,12 +700,14 @@ static int my_pthread_mutex_unlock(pthre + return pthread_mutex_unlock(realmutex); } --static Elf32_Sym * -+static Elf_Sym * - _do_lookup(soinfo *si, const char *name, unsigned *base) +-static int my_pthread_mutex_lock_timeout_np(pthread_mutex_t *__mutex, unsigned __msecs) ++static int _hybris_hook_pthread_mutex_lock_timeout_np(pthread_mutex_t *__mutex, unsigned __msecs) { - unsigned elf_hash = elfhash(name); -- Elf32_Sym *s; -+ Elf_Sym *s; - unsigned *d; - soinfo *lsi = si; - int i; -@@ -501,17 +501,17 @@ done: - /* This is used by dl_sym(). It performs symbol lookup only within the - specified soinfo object and not in any of its dependencies. - */ --Elf32_Sym *lookup_in_library(soinfo *si, const char *name) -+Elf_Sym *lookup_in_library(soinfo *si, const char *name) + struct timespec tv; + pthread_mutex_t *realmutex; + unsigned int value = (*(unsigned int *) __mutex); + ++ TRACE_HOOK("mutex %p msecs %u", __mutex, __msecs); ++ + if (hybris_check_android_shared_mutex(value)) { + LOGD("Shared mutex with Android, not lock timeout np."); + return 0; +@@ -515,9 +731,36 @@ static int my_pthread_mutex_lock_timeout + return pthread_mutex_timedlock(realmutex, &tv); + } + +-static int my_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, ++static int _hybris_hook_pthread_mutex_timedlock(pthread_mutex_t *__mutex, ++ const struct timespec *__abs_timeout) ++{ ++ TRACE_HOOK("mutex %p abs timeout %p", __mutex, __abs_timeout); ++ ++ if (!__mutex) { ++ LOGD("Null mutex lock, not unlocking."); ++ return 0; ++ } ++ ++ unsigned int value = (*(unsigned int *) __mutex); ++ if (hybris_check_android_shared_mutex(value)) { ++ LOGD("Shared mutex with Android, not lock timeout np."); ++ return 0; ++ } ++ ++ pthread_mutex_t *realmutex = (pthread_mutex_t *) value; ++ if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) { ++ realmutex = hybris_alloc_init_mutex(value); ++ *((int *)__mutex) = (int) realmutex; ++ } ++ ++ return pthread_mutex_timedlock(realmutex, __abs_timeout); ++} ++ ++static int _hybris_hook_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, + int pshared) { - return _elf_lookup(si, elfhash(name), name); ++ TRACE_HOOK("attr %p pshared %d", __attr, pshared); ++ + return pthread_mutexattr_setpshared(__attr, pshared); } - /* This is used by dl_sym(). It performs a global symbol lookup. - */ --Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) -+Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start) +@@ -529,11 +772,13 @@ static int my_pthread_mutexattr_setpshar + * + * */ + +-static int my_pthread_cond_init(pthread_cond_t *cond, ++static int _hybris_hook_pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr) { - unsigned elf_hash = elfhash(name); -- Elf32_Sym *s = NULL; -+ Elf_Sym *s = NULL; - soinfo *si; + pthread_cond_t *realcond = NULL; - if(start == NULL) { -@@ -552,7 +552,7 @@ soinfo *find_containing_library(const vo - return NULL; ++ TRACE_HOOK("cond %p attr %p", cond, attr); ++ + int pshared = 0; + + if (attr) +@@ -558,11 +803,13 @@ static int my_pthread_cond_init(pthread_ + return pthread_cond_init(realcond, attr); } --Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) -+Elf_Sym *find_containing_symbol(const void *addr, soinfo *si) +-static int my_pthread_cond_destroy(pthread_cond_t *cond) ++static int _hybris_hook_pthread_cond_destroy(pthread_cond_t *cond) { - unsigned int i; - unsigned soaddr = (unsigned)addr - si->base; -@@ -560,7 +560,7 @@ Elf32_Sym *find_containing_symbol(const - /* Search the library's symbol table for any defined symbol which - * contains this address */ - for(i=0; inchain; i++) { -- Elf32_Sym *sym = &si->symtab[i]; -+ Elf_Sym *sym = &si->symtab[i]; + int ret; + pthread_cond_t *realcond = (pthread_cond_t *) *(unsigned int *) cond; - if(sym->st_shndx != SHN_UNDEF && - soaddr >= sym->st_value && -@@ -575,7 +575,7 @@ Elf32_Sym *find_containing_symbol(const - #if 0 - static void dump(soinfo *si) - { -- Elf32_Sym *s = si->symtab; -+ Elf_Sym *s = si->symtab; - unsigned n; ++ TRACE_HOOK("cond %p", cond); ++ + if (!realcond) { + return EINVAL; + } +@@ -581,12 +828,15 @@ static int my_pthread_cond_destroy(pthre + return ret; + } - for(n = 0; n < si->nchain; n++) { -@@ -704,7 +704,7 @@ is_prelinked(int fd, const char *name) - static int - verify_elf_object(void *base, const char *name) +-static int my_pthread_cond_broadcast(pthread_cond_t *cond) ++static int _hybris_hook_pthread_cond_broadcast(pthread_cond_t *cond) { -- Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; -+ Elf_Ehdr *hdr = (Elf_Ehdr *) base; + unsigned int value = (*(unsigned int *) cond); ++ ++ TRACE_HOOK("cond %p", cond); ++ + if (hybris_check_android_shared_cond(value)) { +- LOGD("shared condition with Android, not broadcasting."); +- return 0; ++ LOGD("Shared condition with Android, broadcasting with futex."); ++ return android_pthread_cond_broadcast((android_cond_t *) cond); + } - if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; - if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; -@@ -749,8 +749,8 @@ get_lib_extents(int fd, const char *name - unsigned min_vaddr = 0xffffffff; - unsigned max_vaddr = 0; - unsigned char *_hdr = (unsigned char *)__hdr; -- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; -- Elf32_Phdr *phdr; -+ Elf_Ehdr *ehdr = (Elf_Ehdr *)_hdr; -+ Elf_Phdr *phdr; - int cnt; + pthread_cond_t *realcond = (pthread_cond_t *) value; +@@ -601,13 +851,15 @@ static int my_pthread_cond_broadcast(pth + return pthread_cond_broadcast(realcond); + } - TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); -@@ -769,7 +769,7 @@ get_lib_extents(int fd, const char *name - TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); +-static int my_pthread_cond_signal(pthread_cond_t *cond) ++static int _hybris_hook_pthread_cond_signal(pthread_cond_t *cond) + { + unsigned int value = (*(unsigned int *) cond); + ++ TRACE_HOOK("cond %p", cond); ++ + if (hybris_check_android_shared_cond(value)) { +- LOGD("Shared condition with Android, not signaling."); +- return 0; ++ LOGD("Shared condition with Android, broadcasting with futex."); ++ return android_pthread_cond_signal((android_cond_t *) cond); } -- phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); -+ phdr = (Elf_Phdr *)(_hdr + ehdr->e_phoff); + pthread_cond_t *realcond = (pthread_cond_t *) value; +@@ -622,12 +874,14 @@ static int my_pthread_cond_signal(pthrea + return pthread_cond_signal(realcond); + } - /* find the min/max p_vaddrs from all the PT_LOAD segments so we can - * get the range. */ -@@ -884,12 +884,12 @@ err: - static int - load_segments(int fd, void *header, soinfo *si) +-static int my_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) ++static int _hybris_hook_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { -- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; -- Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); -- Elf32_Addr base = (Elf32_Addr) si->base; -+ Elf_Ehdr *ehdr = (Elf_Ehdr *)header; -+ Elf_Phdr *phdr = (Elf_Phdr *)((unsigned char *)header + ehdr->e_phoff); -+ Elf_Addr base = (Elf_Addr) si->base; - int cnt; - unsigned len; -- Elf32_Addr tmp; -+ Elf_Addr tmp; - unsigned char *pbase; - unsigned char *extra_base; - unsigned extra_len; -@@ -955,7 +955,7 @@ load_segments(int fd, void *header, soin - * | | - * _+---------------------+ page boundary - */ -- tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & -+ tmp = (Elf_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & - (~PAGE_MASK)); - if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { - extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; -@@ -1019,7 +1019,7 @@ load_segments(int fd, void *header, soin - phdr->p_vaddr, phdr->p_memsz); - goto fail; - } -- si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr); -+ si->gnu_relro_start = (Elf_Addr) (base + phdr->p_vaddr); - si->gnu_relro_len = (unsigned) phdr->p_memsz; - } else { - #ifdef ANDROID_ARM_LINKER -@@ -1066,11 +1066,11 @@ fail: - */ - #if 0 - static unsigned --get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) -+get_wr_offset(int fd, const char *name, Elf_Ehdr *ehdr) + /* Both cond and mutex can be statically initialized, check for both */ + unsigned int cvalue = (*(unsigned int *) cond); + unsigned int mvalue = (*(unsigned int *) mutex); + ++ TRACE_HOOK("cond %p mutex %p", cond, mutex); ++ + if (hybris_check_android_shared_cond(cvalue) || + hybris_check_android_shared_mutex(mvalue)) { + LOGD("Shared condition/mutex with Android, not waiting."); +@@ -655,13 +909,15 @@ static int my_pthread_cond_wait(pthread_ + return pthread_cond_wait(realcond, realmutex); + } + +-static int my_pthread_cond_timedwait(pthread_cond_t *cond, ++static int _hybris_hook_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *abstime) { -- Elf32_Shdr *shdr_start; -- Elf32_Shdr *shdr; -- int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); -+ Elf_Shdr *shdr_start; -+ Elf_Shdr *shdr; -+ int shdr_sz = ehdr->e_shnum * sizeof(Elf_Shdr); - int cnt; - unsigned wr_offset = 0xffffffff; + /* Both cond and mutex can be statically initialized, check for both */ + unsigned int cvalue = (*(unsigned int *) cond); + unsigned int mvalue = (*(unsigned int *) mutex); + ++ TRACE_HOOK("cond %p mutex %p abstime %p", cond, mutex, abstime); ++ + if (hybris_check_android_shared_cond(cvalue) || + hybris_check_android_shared_mutex(mvalue)) { + LOGD("Shared condition/mutex with Android, not waiting."); +@@ -689,13 +945,15 @@ static int my_pthread_cond_timedwait(pth + return pthread_cond_timedwait(realcond, realmutex, abstime); + } -@@ -1103,7 +1103,7 @@ load_library(const char *name) - unsigned req_base; - const char *bname; - soinfo *si = NULL; -- Elf32_Ehdr *hdr; -+ Elf_Ehdr *hdr; +-static int my_pthread_cond_timedwait_relative_np(pthread_cond_t *cond, ++static int _hybris_hook_pthread_cond_timedwait_relative_np(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *reltime) + { + /* Both cond and mutex can be statically initialized, check for both */ + unsigned int cvalue = (*(unsigned int *) cond); + unsigned int mvalue = (*(unsigned int *) mutex); + ++ TRACE_HOOK("cond %p mutex %p reltime %p", cond, mutex, reltime); ++ + if (hybris_check_android_shared_cond(cvalue) || + hybris_check_android_shared_mutex(mvalue)) { + LOGD("Shared condition/mutex with Android, not waiting."); +@@ -731,6 +989,30 @@ static int my_pthread_cond_timedwait_rel + return pthread_cond_timedwait(realcond, realmutex, &tv); + } - if(fd == -1) { - DL_ERR("Library '%s' not found", name); -@@ -1160,8 +1160,8 @@ load_library(const char *name) ++int _hybris_hook_pthread_setname_np(pthread_t thread, const char *name) ++{ ++ TRACE_HOOK("thread %llu name %s", (unsigned long long) thread, name); ++ ++#ifdef MALI_QUIRKS ++ if (strcmp(name, MALI_HIST_DUMP_THREAD_NAME) == 0) { ++ HYBRIS_DEBUG_LOG(HOOKS, "%s: Found mali-hist-dump thread, killing it ...", ++ __FUNCTION__); ++ ++ if (thread != pthread_self()) { ++ HYBRIS_DEBUG_LOG(HOOKS, "%s: -> Failed, as calling thread is not mali-hist-dump itself", ++ __FUNCTION__); ++ return; ++ } ++ ++ pthread_exit((void*) thread); ++ ++ return; ++ } ++#endif ++ ++ return pthread_setname_np(thread, name); ++} ++ + /* + * pthread_rwlockattr_* functions + * +@@ -739,41 +1021,69 @@ static int my_pthread_cond_timedwait_rel + * + * */ - /* this might not be right. Technically, we don't even need this info - * once we go through 'load_segments'. */ -- hdr = (Elf32_Ehdr *)si->base; -- si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); -+ hdr = (Elf_Ehdr *)si->base; -+ si->phdr = (Elf_Phdr *)((unsigned char *)si->base + hdr->e_phoff); - si->phnum = hdr->e_phnum; - /**/ +-static int my_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr) ++static int _hybris_hook_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr) + { + pthread_rwlockattr_t *realattr; -@@ -1260,7 +1260,7 @@ unsigned unload_library(soinfo *si) - * in link_image. This is needed to undo the DT_NEEDED hack below. - */ - if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) { -- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); -+ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); - unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; - if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0) - DL_ERR("%5d %s: could not undo GNU_RELRO protections. " -@@ -1303,16 +1303,16 @@ unsigned unload_library(soinfo *si) ++ TRACE_HOOK("attr %p", __attr); ++ + realattr = malloc(sizeof(pthread_rwlockattr_t)); + *((unsigned int *)__attr) = (unsigned int) realattr; + + return pthread_rwlockattr_init(realattr); } - /* TODO: don't use unsigned for addrs below. It works, but is not -- * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned -+ * ideal. They should probably be either uint32_t, Elf_Addr, or unsigned - * long. - */ --static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) -+static int reloc_library(soinfo *si, Elf_Rel *rel, unsigned count) +-static int my_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr) ++static int _hybris_hook_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr) { -- Elf32_Sym *symtab = si->symtab; -+ Elf_Sym *symtab = si->symtab; - const char *strtab = si->strtab; -- Elf32_Sym *s; -+ Elf_Sym *s; - unsigned base; -- Elf32_Rel *start = rel; -+ Elf_Rel *start = rel; - unsigned idx; + int ret; + pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; - for (idx = 0; idx < count; ++idx) { -@@ -1711,7 +1711,7 @@ static int nullify_closed_stdio (void) - static int link_image(soinfo *si, unsigned wr_offset) ++ TRACE_HOOK("attr %p", __attr); ++ + ret = pthread_rwlockattr_destroy(realattr); + free(realattr); + + return ret; + } + +-static int my_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr, ++static int _hybris_hook_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr, + int pshared) { - unsigned *d; -- Elf32_Phdr *phdr = si->phdr; -+ Elf_Phdr *phdr = si->phdr; - int phnum = si->phnum; + pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p pshared %d", __attr, pshared); ++ + return pthread_rwlockattr_setpshared(realattr, pshared); + } - INFO("[ %5d linking %s ]\n", pid, si->name); -@@ -1794,7 +1794,7 @@ static int link_image(soinfo *si, unsign - phdr->p_vaddr, phdr->p_memsz); - goto fail; - } -- si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr); -+ si->gnu_relro_start = (Elf_Addr) (si->base + phdr->p_vaddr); - si->gnu_relro_len = (unsigned) phdr->p_memsz; - } - } -@@ -1821,7 +1821,7 @@ static int link_image(soinfo *si, unsign - si->strtab = (const char *) (si->base + *d); - break; - case DT_SYMTAB: -- si->symtab = (Elf32_Sym *) (si->base + *d); -+ si->symtab = (Elf_Sym *) (si->base + *d); - break; - case DT_PLTREL: - if(*d != DT_REL) { -@@ -1830,13 +1830,13 @@ static int link_image(soinfo *si, unsign - } - break; - case DT_JMPREL: -- si->plt_rel = (Elf32_Rel*) (si->base + *d); -+ si->plt_rel = (Elf_Rel*) (si->base + *d); - break; - case DT_PLTRELSZ: - si->plt_rel_count = *d / 8; - break; - case DT_REL: -- si->rel = (Elf32_Rel*) (si->base + *d); -+ si->rel = (Elf_Rel*) (si->base + *d); - break; - case DT_RELSZ: - si->rel_count = *d / 8; -@@ -1868,7 +1868,7 @@ static int link_image(soinfo *si, unsign - pid, si->name, si->init_array); - break; - case DT_INIT_ARRAYSZ: -- si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); -+ si->init_array_count = ((unsigned)*d) / sizeof(Elf_Addr); - break; - case DT_FINI_ARRAY: - si->fini_array = (unsigned *)(si->base + *d); -@@ -1876,7 +1876,7 @@ static int link_image(soinfo *si, unsign - pid, si->name, si->fini_array); - break; - case DT_FINI_ARRAYSZ: -- si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); -+ si->fini_array_count = ((unsigned)*d) / sizeof(Elf_Addr); - break; - case DT_PREINIT_ARRAY: - si->preinit_array = (unsigned *)(si->base + *d); -@@ -1884,7 +1884,7 @@ static int link_image(soinfo *si, unsign - pid, si->name, si->preinit_array); - break; - case DT_PREINIT_ARRAYSZ: -- si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); -+ si->preinit_array_count = ((unsigned)*d) / sizeof(Elf_Addr); - break; - case DT_TEXTREL: - /* TODO: make use of this. */ -@@ -1986,7 +1986,7 @@ static int link_image(soinfo *si, unsign - #endif +-static int my_pthread_rwlockattr_getpshared(pthread_rwlockattr_t *__attr, ++static int _hybris_hook_pthread_rwlockattr_getpshared(pthread_rwlockattr_t *__attr, + int *pshared) + { + pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p pshared %p", __attr, pshared); ++ + return pthread_rwlockattr_getpshared(realattr, pshared); + } - if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) { -- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); -+ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); - unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; - if (mprotect((void *) start, len, PROT_READ) < 0) { - DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n", -@@ -2169,7 +2169,7 @@ sanitize: - while(vecs[0] != 0){ - switch(vecs[0]){ - case AT_PHDR: -- si->phdr = (Elf32_Phdr*) vecs[1]; -+ si->phdr = (Elf_Phdr*) vecs[1]; - break; - case AT_PHNUM: - si->phnum = (int) vecs[1]; -@@ -2189,7 +2189,7 @@ sanitize: - si->base = 0; - for ( nn = 0; nn < si->phnum; nn++ ) { - if (si->phdr[nn].p_type == PT_PHDR) { -- si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_vaddr; -+ si->base = (Elf_Addr) si->phdr - si->phdr[nn].p_vaddr; - break; - } - } -@@ -2302,9 +2302,9 @@ static unsigned find_linker_base(unsigne - */ - unsigned __linker_init(unsigned **elfdata) { - unsigned linker_addr = find_linker_base(elfdata); -- Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_addr; -- Elf32_Phdr *phdr = -- (Elf32_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); -+ Elf_Ehdr *elf_hdr = (Elf_Ehdr *) linker_addr; -+ Elf_Phdr *phdr = -+ (Elf_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); ++int _hybris_hook_pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref) ++{ ++ pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) attr; ++ ++ TRACE_HOOK("attr %p pref %i", attr, pref); ++ ++ return pthread_rwlockattr_setkind_np(realattr, pref); ++} ++ ++int _hybris_hook_pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref) ++{ ++ pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) attr; ++ ++ TRACE_HOOK("attr %p pref %p", attr, pref); ++ ++ return pthread_rwlockattr_getkind_np(realattr, pref); ++} ++ + /* + * pthread_rwlock_* functions + * +@@ -782,13 +1092,15 @@ static int my_pthread_rwlockattr_getpsha + * + * */ - soinfo linker_so; - memset(&linker_so, 0, sizeof(soinfo)); ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker.h -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.h -@@ -38,6 +38,26 @@ - #define PAGE_SIZE 4096 - #define PAGE_MASK 4095 +-static int my_pthread_rwlock_init(pthread_rwlock_t *__rwlock, ++static int _hybris_hook_pthread_rwlock_init(pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr) + { + pthread_rwlock_t *realrwlock = NULL; + pthread_rwlockattr_t *realattr = NULL; + int pshared = 0; -+#if defined(__x86_64__) -+typedef Elf64_Ehdr Elf_Ehdr; -+typedef Elf64_Shdr Elf_Shdr; -+typedef Elf64_Sym Elf_Sym; -+typedef Elf64_Addr Elf_Addr; -+typedef Elf64_Phdr Elf_Phdr; -+typedef Elf64_Half Elf_Half; -+typedef Elf64_Rel Elf_Rel; -+typedef Elf64_Rela Elf_Rela; -+#else -+typedef Elf32_Ehdr Elf_Ehdr; -+typedef Elf32_Shdr Elf_Shdr; -+typedef Elf32_Sym Elf_Sym; -+typedef Elf32_Addr Elf_Addr; -+typedef Elf32_Phdr Elf_Phdr; -+typedef Elf32_Half Elf_Half; -+typedef Elf32_Rel Elf_Rel; -+typedef Elf32_Rela Elf_Rela; -+#endif ++ TRACE_HOOK("rwlock %p attr %p", __rwlock, __attr); + - void debugger_init(); - const char *addr_to_name(unsigned addr); + if (__attr != NULL) + realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; + +@@ -814,11 +1126,13 @@ static int my_pthread_rwlock_init(pthrea + return pthread_rwlock_init(realrwlock, realattr); + } + +-static int my_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock) + { + int ret; + pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) *(unsigned int *) __rwlock; + ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + if (!hybris_is_pointer_in_shm((void*)realrwlock)) { + ret = pthread_rwlock_destroy(realrwlock); + free(realrwlock); +@@ -835,6 +1149,7 @@ static pthread_rwlock_t* hybris_set_real + { + unsigned int value = (*(unsigned int *) rwlock); + pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) value; ++ + if (hybris_is_pointer_in_shm((void*)value)) + realrwlock = (pthread_rwlock_t *)hybris_get_shmpointer((hybris_shm_pointer_t)value); + +@@ -845,52 +1160,74 @@ static pthread_rwlock_t* hybris_set_real + return realrwlock; + } + +-static int my_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_rdlock(realrwlock); + } + +-static int my_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_tryrdlock(realrwlock); + } + +-static int my_pthread_rwlock_timedrdlock(pthread_rwlock_t *__rwlock, ++static int _hybris_hook_pthread_rwlock_timedrdlock(pthread_rwlock_t *__rwlock, + __const struct timespec *abs_timeout) + { ++ TRACE_HOOK("rwlock %p abs timeout %p", __rwlock, abs_timeout); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_timedrdlock(realrwlock, abs_timeout); + } + +-static int my_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_wrlock(realrwlock); + } + +-static int my_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_trywrlock(realrwlock); + } + +-static int my_pthread_rwlock_timedwrlock(pthread_rwlock_t *__rwlock, ++static int _hybris_hook_pthread_rwlock_timedwrlock(pthread_rwlock_t *__rwlock, + __const struct timespec *abs_timeout) + { ++ TRACE_HOOK("rwlock %p abs timeout %p", __rwlock, abs_timeout); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_timedwrlock(realrwlock, abs_timeout); + } + +-static int my_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock) + { + unsigned int value = (*(unsigned int *) __rwlock); ++ ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + if (value <= ANDROID_TOP_ADDR_VALUE_RWLOCK) { + LOGD("Trying to unlock a rwlock that's not locked/initialized" + " by Hybris, not unlocking."); + return 0; + } ++ + pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) value; + if (hybris_is_pointer_in_shm((void*)value)) + realrwlock = (pthread_rwlock_t *)hybris_get_shmpointer((hybris_shm_pointer_t)value); +@@ -898,10 +1235,27 @@ static int my_pthread_rwlock_unlock(pthr + return pthread_rwlock_unlock(realrwlock); + } + ++#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) + +-static int my_set_errno(int oi_errno) ++static pid_t _hybris_hook_pthread_gettid(pthread_t t) + { ++ TRACE_HOOK("thread %lu", (unsigned long) t); ++ ++ // glibc doesn't offer us a way to retrieve the thread id for a ++ // specific thread. However pthread_t is defined as unsigned ++ // long int and is the thread id so we can just copy it over ++ // into a pid_t. ++ pid_t tid; ++ memcpy(&tid, &t, min(sizeof(tid), sizeof(t))); ++ return tid; ++} ++ ++static int _hybris_hook_set_errno(int oi_errno) ++{ ++ TRACE_HOOK("errno %d", oi_errno); ++ + errno = oi_errno; ++ + return -1; + } + +@@ -916,7 +1270,7 @@ static int my_set_errno(int oi_errno) + * instead of calling one of the hooked methods. + * Therefore we need to set __isthreaded to true, even if we are not in a multi-threaded context. + */ +-static int __my_isthreaded = 1; ++static int ___hybris_hook_isthreaded = 1; + + /* + * redirection for bionic's __sF, which is defined as: +@@ -930,64 +1284,82 @@ static int __my_isthreaded = 1; + * Currently, only fputs is managed. + */ + #define BIONIC_SIZEOF_FILE 84 +-static char my_sF[3*BIONIC_SIZEOF_FILE] = {0}; ++static char _hybris_hook_sF[3*BIONIC_SIZEOF_FILE] = {0}; + static FILE *_get_actual_fp(FILE *fp) + { + char *c_fp = (char*)fp; +- if (c_fp == &my_sF[0]) ++ if (c_fp == &_hybris_hook_sF[0]) + return stdin; +- else if (c_fp == &my_sF[BIONIC_SIZEOF_FILE]) ++ else if (c_fp == &_hybris_hook_sF[BIONIC_SIZEOF_FILE]) + return stdout; +- else if (c_fp == &my_sF[BIONIC_SIZEOF_FILE*2]) ++ else if (c_fp == &_hybris_hook_sF[BIONIC_SIZEOF_FILE*2]) + return stderr; + + return fp; + } + +-static void my_clearerr(FILE *fp) ++static void _hybris_hook_clearerr(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + clearerr(_get_actual_fp(fp)); + } + +-static int my_fclose(FILE *fp) ++static int _hybris_hook_fclose(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fclose(_get_actual_fp(fp)); + } + +-static int my_feof(FILE *fp) ++static int _hybris_hook_feof(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return feof(_get_actual_fp(fp)); + } + +-static int my_ferror(FILE *fp) ++static int _hybris_hook_ferror(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ferror(_get_actual_fp(fp)); + } + +-static int my_fflush(FILE *fp) ++static int _hybris_hook_fflush(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fflush(_get_actual_fp(fp)); + } + +-static int my_fgetc(FILE *fp) ++static int _hybris_hook_fgetc(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fgetc(_get_actual_fp(fp)); + } + +-static int my_fgetpos(FILE *fp, fpos_t *pos) ++static int _hybris_hook_fgetpos(FILE *fp, fpos_t *pos) + { ++ TRACE_HOOK("fp %p pos %p", fp, pos); ++ + return fgetpos(_get_actual_fp(fp), pos); + } + +-static char* my_fgets(char *s, int n, FILE *fp) ++static char* _hybris_hook_fgets(char *s, int n, FILE *fp) + { ++ TRACE_HOOK("s %s n %d fp %p", s, n, fp); ++ + return fgets(s, n, _get_actual_fp(fp)); + } + +-FP_ATTRIB static int my_fprintf(FILE *fp, const char *fmt, ...) ++FP_ATTRIB static int _hybris_hook_fprintf(FILE *fp, const char *fmt, ...) + { + int ret = 0; + ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + va_list args; + va_start(args,fmt); + ret = vfprintf(_get_actual_fp(fp), fmt, args); +@@ -996,30 +1368,40 @@ FP_ATTRIB static int my_fprintf(FILE *fp + return ret; + } + +-static int my_fputc(int c, FILE *fp) ++static int _hybris_hook_fputc(int c, FILE *fp) + { ++ TRACE_HOOK("c %d fp %p", c, fp); ++ + return fputc(c, _get_actual_fp(fp)); + } + +-static int my_fputs(const char *s, FILE *fp) ++static int _hybris_hook_fputs(const char *s, FILE *fp) + { ++ TRACE_HOOK("s '%s' fp %p", s, fp); ++ + return fputs(s, _get_actual_fp(fp)); + } + +-static size_t my_fread(void *ptr, size_t size, size_t nmemb, FILE *fp) ++static size_t _hybris_hook_fread(void *ptr, size_t size, size_t nmemb, FILE *fp) + { ++ TRACE_HOOK("ptr %p size %zu nmemb %zu fp %p", ptr, size, nmemb, fp); ++ + return fread(ptr, size, nmemb, _get_actual_fp(fp)); + } + +-static FILE* my_freopen(const char *filename, const char *mode, FILE *fp) ++static FILE* _hybris_hook_freopen(const char *filename, const char *mode, FILE *fp) + { ++ TRACE_HOOK("filename '%s' mode '%s' fp %p", filename, mode, fp); ++ + return freopen(filename, mode, _get_actual_fp(fp)); + } + +-FP_ATTRIB static int my_fscanf(FILE *fp, const char *fmt, ...) ++FP_ATTRIB static int _hybris_hook_fscanf(FILE *fp, const char *fmt, ...) + { + int ret = 0; + ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + va_list args; + va_start(args,fmt); + ret = vfscanf(_get_actual_fp(fp), fmt, args); +@@ -1028,155 +1410,208 @@ FP_ATTRIB static int my_fscanf(FILE *fp, + return ret; + } + +-static int my_fseek(FILE *fp, long offset, int whence) ++static int _hybris_hook_fseek(FILE *fp, long offset, int whence) + { ++ TRACE_HOOK("fp %p offset %ld whence %d", fp, offset, whence); ++ + return fseek(_get_actual_fp(fp), offset, whence); + } + +-static int my_fseeko(FILE *fp, off_t offset, int whence) ++static int _hybris_hook_fseeko(FILE *fp, off_t offset, int whence) + { ++ TRACE_HOOK("fp %p offset %ld whence %d", fp, offset, whence); ++ + return fseeko(_get_actual_fp(fp), offset, whence); + } + +-static int my_fsetpos(FILE *fp, const fpos_t *pos) ++static int _hybris_hook_fsetpos(FILE *fp, const fpos_t *pos) + { ++ TRACE_HOOK("fp %p pos %p", fp, pos); ++ + return fsetpos(_get_actual_fp(fp), pos); + } + +-static long my_ftell(FILE *fp) ++static long _hybris_hook_ftell(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ftell(_get_actual_fp(fp)); + } + +-static off_t my_ftello(FILE *fp) ++static off_t _hybris_hook_ftello(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ftello(_get_actual_fp(fp)); + } + +-static size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp) ++static size_t _hybris_hook_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp) + { ++ TRACE_HOOK("ptr %p size %zu nmemb %zu fp %p", ptr, size, nmemb, fp); ++ + return fwrite(ptr, size, nmemb, _get_actual_fp(fp)); + } + +-static int my_getc(FILE *fp) ++static int _hybris_hook_getc(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return getc(_get_actual_fp(fp)); + } + +-static ssize_t my_getdelim(char ** lineptr, size_t *n, int delimiter, FILE * fp) ++static ssize_t _hybris_hook_getdelim(char ** lineptr, size_t *n, int delimiter, FILE * fp) + { ++ TRACE_HOOK("lineptr %p n %p delimiter %d fp %p", lineptr, n, delimiter, fp); ++ + return getdelim(lineptr, n, delimiter, _get_actual_fp(fp)); + } + +-static ssize_t my_getline(char **lineptr, size_t *n, FILE *fp) ++static ssize_t _hybris_hook_getline(char **lineptr, size_t *n, FILE *fp) + { ++ TRACE_HOOK("lineptr %p n %p fp %p", lineptr, n, fp); ++ + return getline(lineptr, n, _get_actual_fp(fp)); + } + +- +-static int my_putc(int c, FILE *fp) ++static int _hybris_hook_putc(int c, FILE *fp) + { ++ TRACE_HOOK("c %d fp %p", c, fp); ++ + return putc(c, _get_actual_fp(fp)); + } + +-static void my_rewind(FILE *fp) ++static void _hybris_hook_rewind(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + rewind(_get_actual_fp(fp)); + } + +-static void my_setbuf(FILE *fp, char *buf) ++static void _hybris_hook_setbuf(FILE *fp, char *buf) + { ++ TRACE_HOOK("fp %p buf '%s'", fp, buf); ++ + setbuf(_get_actual_fp(fp), buf); + } + +-static int my_setvbuf(FILE *fp, char *buf, int mode, size_t size) ++static int _hybris_hook_setvbuf(FILE *fp, char *buf, int mode, size_t size) + { ++ TRACE_HOOK("fp %p buf '%s' mode %d size %zu", fp, buf, mode, size); ++ + return setvbuf(_get_actual_fp(fp), buf, mode, size); + } + +-static int my_ungetc(int c, FILE *fp) ++static int _hybris_hook_ungetc(int c, FILE *fp) + { ++ TRACE_HOOK("c %d fp %p", c, fp); ++ + return ungetc(c, _get_actual_fp(fp)); + } + +-static int my_vfprintf(FILE *fp, const char *fmt, va_list arg) ++static int _hybris_hook_vfprintf(FILE *fp, const char *fmt, va_list arg) + { ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + return vfprintf(_get_actual_fp(fp), fmt, arg); + } + +- +-static int my_vfscanf(FILE *fp, const char *fmt, va_list arg) ++static int _hybris_hook_vfscanf(FILE *fp, const char *fmt, va_list arg) + { ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + return vfscanf(_get_actual_fp(fp), fmt, arg); + } + +-static int my_fileno(FILE *fp) ++static int _hybris_hook_fileno(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fileno(_get_actual_fp(fp)); + } + +- +-static int my_pclose(FILE *fp) ++static int _hybris_hook_pclose(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return pclose(_get_actual_fp(fp)); + } + +-static void my_flockfile(FILE *fp) ++static void _hybris_hook_flockfile(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return flockfile(_get_actual_fp(fp)); + } + +-static int my_ftrylockfile(FILE *fp) ++static int _hybris_hook_ftrylockfile(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ftrylockfile(_get_actual_fp(fp)); + } + +-static void my_funlockfile(FILE *fp) ++static void _hybris_hook_funlockfile(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return funlockfile(_get_actual_fp(fp)); + } + +- +-static int my_getc_unlocked(FILE *fp) ++static int _hybris_hook_getc_unlocked(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return getc_unlocked(_get_actual_fp(fp)); + } + +-static int my_putc_unlocked(int c, FILE *fp) ++static int _hybris_hook_putc_unlocked(int c, FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return putc_unlocked(c, _get_actual_fp(fp)); + } + + /* exists only on the BSD platform +-static char* my_fgetln(FILE *fp, size_t *len) ++static char* _hybris_hook_fgetln(FILE *fp, size_t *len) + { + return fgetln(_get_actual_fp(fp), len); + } + */ +-static int my_fpurge(FILE *fp) ++ ++static int _hybris_hook_fpurge(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + __fpurge(_get_actual_fp(fp)); + + return 0; + } + +-static int my_getw(FILE *fp) ++static int _hybris_hook_getw(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return getw(_get_actual_fp(fp)); + } + +-static int my_putw(int w, FILE *fp) ++static int _hybris_hook_putw(int w, FILE *fp) + { ++ TRACE_HOOK("w %d fp %p", w, fp); ++ + return putw(w, _get_actual_fp(fp)); + } + +-static void my_setbuffer(FILE *fp, char *buf, int size) ++static void _hybris_hook_setbuffer(FILE *fp, char *buf, int size) + { ++ TRACE_HOOK("fp %p buf '%s' size %d", fp, buf, size); ++ + setbuffer(_get_actual_fp(fp), buf, size); + } + +-static int my_setlinebuf(FILE *fp) ++static int _hybris_hook_setlinebuf(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + setlinebuf(_get_actual_fp(fp)); + + return 0; +@@ -1191,7 +1626,7 @@ struct bionic_dirent { + char d_name[256]; + }; + +-static struct bionic_dirent *my_readdir(DIR *dirp) ++static struct bionic_dirent *_hybris_hook_readdir(DIR *dirp) + { + /** + * readdir(3) manpage says: +@@ -1207,6 +1642,8 @@ static struct bionic_dirent *my_readdir( + + static struct bionic_dirent result; + ++ TRACE_HOOK("dirp %p", dirp); ++ + struct dirent *real_result = readdir(dirp); + if (!real_result) { + return NULL; +@@ -1225,12 +1662,14 @@ static struct bionic_dirent *my_readdir( + return &result; + } + +-static int my_readdir_r(DIR *dir, struct bionic_dirent *entry, ++static int _hybris_hook_readdir_r(DIR *dir, struct bionic_dirent *entry, + struct bionic_dirent **result) + { + struct dirent entry_r; + struct dirent *result_r; + ++ TRACE_HOOK("dir %p entry %p result %p", dir, entry, result); ++ + int res = readdir_r(dir, &entry_r, &result_r); + + if (res == 0) { +@@ -1255,89 +1694,612 @@ static int my_readdir_r(DIR *dir, struct + return res; + } + +-extern long my_sysconf(int name); ++static int _hybris_hook_alphasort(struct bionic_dirent **a, ++ struct bionic_dirent **b) ++{ ++ return strcoll((*a)->d_name, (*b)->d_name); ++} + +-FP_ATTRIB static double my_strtod(const char *nptr, char **endptr) ++static int _hybris_hook_versionsort(struct bionic_dirent **a, ++ struct bionic_dirent **b) + { +- if (locale_inited == 0) +- { +- hybris_locale = newlocale(LC_ALL_MASK, "C", 0); +- locale_inited = 1; +- } +- return strtod_l(nptr, endptr, hybris_locale); ++ return strverscmp((*a)->d_name, (*b)->d_name); + } + +-extern int __cxa_atexit(void (*)(void*), void*, void*); +-extern void __cxa_finalize(void * d); ++static struct bionic_dirent *_hybris_hook_scandirat(int fd, DIR *dirp, struct bionic_dirent ***namelist, ++ int (*filter)(const struct bionic_dirent *), ++ int (*compar)(const struct bionic_dirent **, const struct bionic_dirent **)) ++{ ++ struct dirent **namelist_r; ++ static struct bionic_dirent **result; ++ struct bionic_dirent *filter_r; + +-struct open_redirect { +- const char *from; +- const char *to; +-}; ++ int i = 0; ++ size_t nItems = 0; + +-struct open_redirect open_redirects[] = { +- { "/dev/log/main", "/dev/log_main" }, +- { "/dev/log/radio", "/dev/log_radio" }, +- { "/dev/log/system", "/dev/log_system" }, +- { "/dev/log/events", "/dev/log_events" }, +- { NULL, NULL } +-}; ++ TRACE_HOOK("dirp %p", dirp); + +-int my_open(const char *pathname, int flags, ...) +-{ +- va_list ap; +- mode_t mode = 0; +- const char *target_path = pathname; +- +- if (pathname != NULL) { +- struct open_redirect *entry = &open_redirects[0]; +- while (entry->from != NULL) { +- if (strcmp(pathname, entry->from) == 0) { +- target_path = entry->to; +- break; +- } +- entry++; +- } +- } +- +- if (flags & O_CREAT) { +- va_start(ap, flags); +- mode = va_arg(ap, mode_t); +- va_end(ap); +- } ++ int res = scandirat(fd, dirp, &namelist_r, NULL, NULL); + +- return open(target_path, flags, mode); +-} ++ if (res != 0 && namelist_r != NULL) { + +-/** +- * NOTE: Normally we don't have to wrap __system_property_get (libc.so) as it is only used +- * through the property_get (libcutils.so) function. However when property_get is used +- * internally in libcutils.so we don't have any chance to hook our replacement in. +- * Therefore we have to hook __system_property_get too and just replace it with the +- * implementation of our internal property handling +- */ ++ result = malloc(res * sizeof(struct bionic_dirent)); ++ if (!result) ++ return -1; + +-int my_system_property_get(const char *name, const char *value) +-{ +- return property_get(name, value, NULL); ++ for (i = 0; i < res; i++) { ++ filter_r = malloc(sizeof(struct bionic_dirent)); ++ if (!filter_r) { ++ while (i-- > 0) ++ free(result[i]); ++ free(result); ++ return -1; ++ } ++ filter_r->d_ino = namelist_r[i]->d_ino; ++ filter_r->d_off = namelist_r[i]->d_off; ++ filter_r->d_reclen = namelist_r[i]->d_reclen; ++ filter_r->d_type = namelist_r[i]->d_type; ++ ++ strcpy(filter_r->d_name, namelist_r[i]->d_name); ++ filter_r->d_name[sizeof(namelist_r[i]->d_name) - 1] = '\0'; ++ ++ if (filter != NULL && !(*filter)(filter_r)) {//apply filter ++ free(filter_r); ++ continue; ++ } ++ ++ result[nItems++] = filter_r; ++ } ++ if (nItems && compar != NULL) ++ qsort(result, nItems, sizeof(struct bionic_dirent *), compar); ++ ++ *namelist = result; ++ } ++ ++ return res; + } + +-static __thread void *tls_hooks[16]; ++static struct bionic_dirent *_hybris_hook_scandir(DIR *dirp, struct bionic_dirent ***namelist, ++ int (*filter)(const struct bionic_dirent *), ++ int (*compar)(const struct bionic_dirent **, const struct bionic_dirent **)) ++{ ++ return _hybris_hook_scandirat(AT_FDCWD, dirp, namelist, filter, compar); ++} + +-void *__get_tls_hooks() ++static inline void swap(void **a, void **b) + { +- return tls_hooks; ++ void *tmp = *a; ++ *a = *b; ++ *b = tmp; + } + +-static struct _hook hooks[] = { +- {"property_get", property_get }, +- {"property_set", property_set }, +- {"__system_property_get", my_system_property_get }, +- {"getenv", getenv }, +- {"printf", printf }, +- {"malloc", my_malloc }, +- {"free", free }, +- {"calloc", calloc }, ++static int _hybris_hook_getaddrinfo(const char *hostname, const char *servname, ++ const struct addrinfo *hints, struct addrinfo **res) ++{ ++ struct addrinfo *fixed_hints = NULL; ++ ++ TRACE_HOOK("hostname '%s' servname '%s' hints %p res %p", ++ hostname, servname, hints, res); ++ ++ if (hints) { ++ fixed_hints = (struct addrinfo*) malloc(sizeof(struct addrinfo)); ++ memcpy(fixed_hints, hints, sizeof(struct addrinfo)); ++ // fix bionic -> glibc missmatch ++ swap((void**)&(fixed_hints->ai_canonname), (void**)&(fixed_hints->ai_addr)); ++ } ++ ++ int result = getaddrinfo(hostname, servname, fixed_hints, res); ++ ++ if (fixed_hints) ++ free(fixed_hints); ++ ++ // fix bionic <- glibc missmatch ++ struct addrinfo *it = *res; ++ while (it) { ++ swap((void**) &(it->ai_canonname), (void**) &(it->ai_addr)); ++ it = it->ai_next; ++ } ++ ++ return result; ++} ++ ++static void _hybris_hook_freeaddrinfo(struct addrinfo *__ai) ++{ ++ TRACE_HOOK("ai %p", __ai); ++ ++ if (__ai == NULL) ++ return; ++ ++ struct addrinfo *it = __ai; ++ while (it) { ++ swap((void**) &(it->ai_canonname), (void**) &(it->ai_addr)); ++ it = it->ai_next; ++ } ++ ++ freeaddrinfo(__ai); ++} ++ ++extern long _hybris_map_sysconf(int name); ++ ++long _hybris_hook_sysconf(int name) ++{ ++ TRACE_HOOK("name %d", name); ++ ++ return _hybris_map_sysconf(name); ++} ++ ++FP_ATTRIB static double _hybris_hook_strtod(const char *nptr, char **endptr) ++{ ++ TRACE_HOOK("nptr '%s' endptr %p", nptr, endptr); ++ ++ if (locale_inited == 0) { ++ hybris_locale = newlocale(LC_ALL_MASK, "C", 0); ++ locale_inited = 1; ++ } ++ ++ return strtod_l(nptr, endptr, hybris_locale); ++} ++ ++static long int _hybris_hook_strtol(const char* str, char** endptr, int base) ++{ ++ TRACE_HOOK("str '%s' endptr %p base %i", str, endptr, base); ++ ++ return strtol(str, endptr, base); ++} ++ ++static int ___hybris_hook_system_property_read(const void *pi, char *name, char *value) ++{ ++ TRACE_HOOK("pi %p name '%s' value '%s'", pi, name, value); ++ ++ return property_get(name, value, NULL); ++} ++ ++static int ___hybris_hook_system_property_foreach(void (*propfn)(const void *pi, void *cookie), void *cookie) ++{ ++ TRACE_HOOK("propfn %p cookie %p", propfn, cookie); ++ ++ return 0; ++} ++ ++static const void *___hybris_hook_system_property_find(const char *name) ++{ ++ TRACE_HOOK("name '%s'", name); ++ ++ return NULL; ++} ++ ++static unsigned int ___hybris_hook_system_property_serial(const void *pi) ++{ ++ TRACE_HOOK("pi %p", pi); ++ ++ return 0; ++} ++ ++static int ___hybris_hook_system_property_wait(const void *pi) ++{ ++ TRACE_HOOK("pi %p", pi); ++ ++ return 0; ++} ++ ++static int ___hybris_hook_system_property_update(void *pi, const char *value, unsigned int len) ++{ ++ TRACE_HOOK("pi %p value '%s' len %d", pi, value, len); ++ ++ return 0; ++} ++ ++static int ___hybris_hook_system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen) ++{ ++ TRACE_HOOK("name '%s' namelen %d value '%s' valuelen %d", ++ name, namelen, value, valuelen); ++ return 0; ++} ++ ++static unsigned int ___hybris_hook_system_property_wait_any(unsigned int serial) ++{ ++ TRACE_HOOK("serial %d", serial); ++ ++ return 0; ++} ++ ++static const void *___hybris_hook_system_property_find_nth(unsigned n) ++{ ++ TRACE_HOOK("n %d", n); ++ ++ return NULL; ++} ++ ++/** ++ * NOTE: Normally we don't have to wrap __system_property_get (libc.so) as it is only used ++ * through the property_get (libcutils.so) function. However when property_get is used ++ * internally in libcutils.so we don't have any chance to hook our replacement in. ++ * Therefore we have to hook __system_property_get too and just replace it with the ++ * implementation of our internal property handling ++ */ ++ ++int _hybris_hook_system_property_get(const char *name, const char *value) ++{ ++ TRACE_HOOK("name '%s' value '%s'", name, value); ++ ++ return property_get(name, (char*) value, NULL); ++} ++ ++int _hybris_hook_property_get(const char *key, char *value, const char *default_value) ++{ ++ TRACE_HOOK("key '%s' value '%s' default value '%s'", ++ key, value, default_value); ++ ++ return property_get(key, value, default_value); ++} ++ ++int _hybris_hook_property_set(const char *key, const char *value) ++{ ++ TRACE_HOOK("key '%s' value '%s'", key, value); ++ ++ return property_set(key, value); ++} ++ ++char *_hybris_hook_getenv(const char *name) ++{ ++ TRACE_HOOK("name '%s'", name); ++ ++ return getenv(name); ++} ++ ++int _hybris_hook_setenv(const char *name, const char *value, int overwrite) ++{ ++ TRACE_HOOK("name '%s' value '%s' overwrite %d", name, value, overwrite); ++ ++ return setenv(name, value, overwrite); ++} ++ ++int _hybris_hook_putenv(char *string) ++{ ++ TRACE_HOOK("string '%s'", string); ++ ++ return putenv(string); ++} ++ ++int _hybris_hook_clearenv(void) ++{ ++ TRACE_HOOK(""); ++ ++ return clearenv(); ++} ++ ++extern int __cxa_atexit(void (*)(void*), void*, void*); ++extern void __cxa_finalize(void * d); ++ ++struct open_redirect { ++ const char *from; ++ const char *to; ++}; ++ ++struct open_redirect open_redirects[] = { ++ { "/dev/log/main", "/dev/alog/main" }, ++ { "/dev/log/radio", "/dev/alog/radio" }, ++ { "/dev/log/system", "/dev/alog/system" }, ++ { "/dev/log/events", "/dev/alog/events" }, ++ { NULL, NULL } ++}; ++ ++int _hybris_hook_open(const char *pathname, int flags, ...) ++{ ++ va_list ap; ++ mode_t mode = 0; ++ const char *target_path = pathname; ++ ++ TRACE_HOOK("pathname '%s' flags %d", pathname, flags); ++ ++ if (pathname != NULL) { ++ struct open_redirect *entry = &open_redirects[0]; ++ while (entry->from != NULL) { ++ if (strcmp(pathname, entry->from) == 0) { ++ target_path = entry->to; ++ break; ++ } ++ entry++; ++ } ++ } ++ ++ if (flags & O_CREAT) { ++ va_start(ap, flags); ++ mode = va_arg(ap, mode_t); ++ va_end(ap); ++ } ++ ++ return open(target_path, flags, mode); ++} ++ ++static __thread void *tls_hooks[16]; ++ ++static void *_hybris_hook_get_tls_hooks() ++{ ++ TRACE_HOOK(""); ++ return tls_hooks; ++} ++ ++int _hybris_hook_prctl(int option, unsigned long arg2, unsigned long arg3, ++ unsigned long arg4, unsigned long arg5) ++{ ++ TRACE_HOOK("option %d arg2 %lu arg3 %lu arg4 %lu arg5 %lu", ++ option, arg2, arg3, arg4, arg5); ++ ++#ifdef MALI_QUIRKS ++ if (option == PR_SET_NAME) { ++ char *name = (char*) arg2; ++ ++ if (strcmp(name, MALI_HIST_DUMP_THREAD_NAME) == 0) { ++ ++ // This can only work because prctl with PR_SET_NAME ++ // can be only called for the current thread and not ++ // for another thread so we can safely pause things. ++ ++ HYBRIS_DEBUG_LOG(HOOKS, "%s: Found mali-hist-dump, killing thread ...", ++ __FUNCTION__); ++ ++ pthread_exit(NULL); ++ } ++ } ++#endif ++ ++ return prctl(option, arg2, arg3, arg4, arg5); ++} ++ ++static char* _hybris_hook_basename(const char *path) ++{ ++ static __thread char buf[PATH_MAX]; ++ ++ TRACE_HOOK("path '%s'", path); ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ if (path) ++ strncpy(buf, path, sizeof(buf)); ++ ++ buf[sizeof buf - 1] = '\0'; ++ ++ return basename(buf); ++} ++ ++static char* _hybris_hook_dirname(char *path) ++{ ++ static __thread char buf[PATH_MAX]; ++ ++ TRACE_HOOK("path '%s'", path); ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ if (path) ++ strncpy(buf, path, sizeof(buf)); ++ ++ buf[sizeof buf - 1] = '\0'; ++ ++ return dirname(path); ++} ++ ++static char* _hybris_hook_strerror(int errnum) ++{ ++ TRACE_HOOK("errnum %d", errnum); ++ ++ return strerror(errnum); ++} ++ ++static char* _hybris_hook__gnu_strerror_r(int errnum, char *buf, size_t buf_len) ++{ ++ TRACE_HOOK("errnum %d buf '%s' buf len %zu", errnum, buf, buf_len); ++ ++ return strerror_r(errnum, buf, buf_len); ++} ++ ++static int _hybris_hook_mprotect(void *addr, size_t len, int prot) ++{ ++ TRACE_HOOK("addr %p len %zu prot %d", addr, len, prot); ++ ++ return mprotect(addr, len, prot); ++} ++ ++static int _hybris_hook_posix_memalign(void **memptr, size_t alignment, size_t size) ++{ ++ TRACE_HOOK("memptr %p alignment %zu size %zu", memptr, alignment, size); ++ ++ return posix_memalign(memptr, alignment, size); ++} ++ ++static pid_t _hybris_hook_fork(void) ++{ ++ TRACE_HOOK(""); ++ ++ return fork(); ++} ++ ++static locale_t _hybris_hook_newlocale(int category_mask, const char *locale, locale_t base) ++{ ++ TRACE_HOOK("category mask %i locale '%s'", category_mask, locale); ++ ++ return newlocale(category_mask, locale, base); ++} ++ ++static void _hybris_hook_freelocale(locale_t locobj) ++{ ++ TRACE_HOOK(""); ++ ++ return freelocale(locobj); ++} ++ ++static locale_t _hybris_hook_duplocale(locale_t locobj) ++{ ++ TRACE_HOOK(""); ++ ++ return duplocale(locobj); ++} ++ ++static locale_t _hybris_hook_uselocale(locale_t newloc) ++{ ++ TRACE_HOOK(""); ++ ++ return uselocale(newloc); ++} ++ ++static struct lconv* _hybris_hook_localeconv(void) ++{ ++ TRACE_HOOK(""); ++ ++ return localeconv(); ++} ++ ++static char* _hybris_hook_setlocale(int category, const char *locale) ++{ ++ TRACE_HOOK("category %i locale '%s'", category, locale); ++ ++ return setlocale(category, locale); ++} ++ ++static void* _hybris_hook_mmap(void *addr, size_t len, int prot, ++ int flags, int fd, off_t offset) ++{ ++ TRACE_HOOK("addr %p len %u prot %i flags %i fd %i offset %u", ++ addr, len, prot, flags, fd, offset); ++ ++ return mmap(addr, len, prot, flags, fd, offset); ++} ++ ++static int _hybris_hook_munmap(void *addr, size_t length) ++{ ++ TRACE_HOOK("addr %p length %u", addr, length); ++ ++ return munmap(addr, length); ++} ++ ++extern size_t strlcat(char *dst, const char *src, size_t siz); ++extern size_t strlcpy(char *dst, const char *src, size_t siz); ++ ++static int _hybris_hook_strcmp(const char *s1, const char *s2) ++{ ++ TRACE_HOOK("s1 '%s' s2 '%s'", s1, s2); ++ ++ if ( s1 == NULL || s2 == NULL) ++ return -1; ++ ++ return strcmp(s1, s2); ++} ++ ++static FILE* _hybris_hook_setmntent(const char *filename, const char *type) ++{ ++ TRACE_HOOK("filename %s type %s", filename, type); ++ ++ return setmntent(filename, type); ++} ++ ++static struct mntent* _hybris_hook_getmntent(FILE *fp) ++{ ++ TRACE_HOOK("fp %p", fp); ++ ++ return getmntent(_get_actual_fp(fp)); ++} ++ ++static struct mntent* _hybris_hook_getmntent_r(FILE *fp, struct mntent *e, char *buf, int buf_len) ++{ ++ TRACE_HOOK("fp %p e %p buf '%s' buf len %i", ++ fp, e, buf, buf_len); ++ ++ return getmntent_r(_get_actual_fp(fp), e, buf, buf_len); ++} ++ ++int _hybris_hook_endmntent(FILE *fp) ++{ ++ TRACE_HOOK("fp %p", fp); ++ ++ return endmntent(_get_actual_fp(fp)); ++} ++ ++static int _hybris_hook_fputws(const wchar_t *ws, FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return fputws(ws, _get_actual_fp(stream)); ++} ++ ++static int _hybris_hook_vfwprintf(FILE *stream, const wchar_t *format, va_list args) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return vfwprintf(_get_actual_fp(stream), format, args); ++} ++ ++static wint_t _hybris_hook_fputwc(wchar_t wc, FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return fputwc(wc, _get_actual_fp(stream)); ++} ++ ++static wint_t _hybris_hook_putwc(wchar_t wc, FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return putwc(wc, _get_actual_fp(stream)); ++} ++ ++static wint_t _hybris_hook_fgetwc(FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return fgetwc(_get_actual_fp(stream)); ++} ++ ++static wint_t _hybris_hook_getwc(FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return getwc(_get_actual_fp(stream)); ++} ++ ++static void *_hybris_hook_android_dlopen(const char *filename, int flag) ++{ ++ TRACE("filename %s flag %i", filename, flag); ++ ++ return _android_dlopen(filename,flag); ++} ++ ++static void *_hybris_hook_android_dlsym(void *handle, const char *symbol) ++{ ++ TRACE("handle %p symbol %s", handle, symbol); ++ ++ return _android_dlsym(handle,symbol); ++} ++ ++static void* _hybris_hook_android_dladdr(void *addr, Dl_info *info) ++{ ++ TRACE("addr %p info %p", addr, info); ++ ++ return _android_dladdr(addr, info); ++} ++ ++static int _hybris_hook_android_dlclose(void *handle) ++{ ++ TRACE("handle %p", handle); ++ ++ return _android_dlclose(handle); ++} ++ ++static const char *_hybris_hook_android_dlerror(void) ++{ ++ TRACE(""); ++ ++ return android_dlerror(); ++} ++ ++static struct _hook hooks_common[] = { ++ {"property_get", _hybris_hook_property_get }, ++ {"property_set", _hybris_hook_property_set }, ++ {"__system_property_get", _hybris_hook_system_property_get }, ++ {"getenv", _hybris_hook_getenv}, ++ {"printf", printf }, ++ {"malloc", _hybris_hook_malloc }, ++ {"free", free }, ++ {"calloc", calloc }, + {"cfree", cfree }, + {"realloc", realloc }, + {"memalign", memalign }, +@@ -1345,22 +2307,24 @@ static struct _hook hooks[] = { + {"pvalloc", pvalloc }, + {"fread", fread }, + {"getxattr", getxattr}, ++ {"mprotect", _hybris_hook_mprotect}, + /* string.h */ + {"memccpy",memccpy}, + {"memchr",memchr}, + {"memrchr",memrchr}, +- {"memcmp",memcmp}, +- {"memcpy",my_memcpy}, ++ {"memcmp",_hybris_hook_memcmp}, ++ {"memcpy",_hybris_hook_memcpy}, + {"memmove",memmove}, + {"memset",memset}, + {"memmem",memmem}, +- // {"memswap",memswap}, ++ {"getlogin", getlogin}, ++ // {"memswap",memswap}, + {"index",index}, + {"rindex",rindex}, + {"strchr",strchr}, + {"strrchr",strrchr}, +- {"strlen",my_strlen}, +- {"strcmp",strcmp}, ++ {"strlen",_hybris_hook_strlen}, ++ {"strcmp",_hybris_hook_strcmp}, + {"strcpy",strcpy}, + {"strcat",strcat}, + {"strcasecmp",strcasecmp}, +@@ -1369,16 +2333,14 @@ static struct _hook hooks[] = { + {"strstr",strstr}, + {"strtok",strtok}, + {"strtok_r",strtok_r}, +- {"strerror",strerror}, ++ {"strerror",_hybris_hook_strerror}, + {"strerror_r",strerror_r}, + {"strnlen",strnlen}, + {"strncat",strncat}, + {"strndup",strndup}, + {"strncmp",strncmp}, + {"strncpy",strncpy}, +- {"strtod", my_strtod}, +- //{"strlcat",strlcat}, +- //{"strlcpy",strlcpy}, ++ {"strtod", _hybris_hook_strtod}, + {"strcspn",strcspn}, + {"strpbrk",strpbrk}, + {"strsep",strsep}, +@@ -1395,17 +2357,19 @@ static struct _hook hooks[] = { + {"index",index}, + {"rindex",rindex}, + {"strcasecmp",strcasecmp}, ++ {"__sprintf_chk", __sprintf_chk}, ++ {"__snprintf_chk", __snprintf_chk}, + {"strncasecmp",strncasecmp}, + /* dirent.h */ + {"opendir", opendir}, + {"closedir", closedir}, + /* pthread.h */ + {"getauxval", getauxval}, +- {"gettid", my_gettid}, ++ {"gettid", _hybris_hook_gettid}, + {"getpid", getpid}, + {"pthread_atfork", pthread_atfork}, +- {"pthread_create", my_pthread_create}, +- {"pthread_kill", pthread_kill}, ++ {"pthread_create", _hybris_hook_pthread_create}, ++ {"pthread_kill", _hybris_hook_pthread_kill}, + {"pthread_exit", pthread_exit}, + {"pthread_join", pthread_join}, + {"pthread_detach", pthread_detach}, +@@ -1413,72 +2377,78 @@ static struct _hook hooks[] = { + {"pthread_equal", pthread_equal}, + {"pthread_getschedparam", pthread_getschedparam}, + {"pthread_setschedparam", pthread_setschedparam}, +- {"pthread_mutex_init", my_pthread_mutex_init}, +- {"pthread_mutex_destroy", my_pthread_mutex_destroy}, +- {"pthread_mutex_lock", my_pthread_mutex_lock}, +- {"pthread_mutex_unlock", my_pthread_mutex_unlock}, +- {"pthread_mutex_trylock", my_pthread_mutex_trylock}, +- {"pthread_mutex_lock_timeout_np", my_pthread_mutex_lock_timeout_np}, ++ {"pthread_mutex_init", _hybris_hook_pthread_mutex_init}, ++ {"pthread_mutex_destroy", _hybris_hook_pthread_mutex_destroy}, ++ {"pthread_mutex_lock", _hybris_hook_pthread_mutex_lock}, ++ {"pthread_mutex_unlock", _hybris_hook_pthread_mutex_unlock}, ++ {"pthread_mutex_trylock", _hybris_hook_pthread_mutex_trylock}, ++ {"pthread_mutex_lock_timeout_np", _hybris_hook_pthread_mutex_lock_timeout_np}, ++ {"pthread_mutex_timedlock", _hybris_hook_pthread_mutex_timedlock}, + {"pthread_mutexattr_init", pthread_mutexattr_init}, + {"pthread_mutexattr_destroy", pthread_mutexattr_destroy}, + {"pthread_mutexattr_gettype", pthread_mutexattr_gettype}, + {"pthread_mutexattr_settype", pthread_mutexattr_settype}, + {"pthread_mutexattr_getpshared", pthread_mutexattr_getpshared}, +- {"pthread_mutexattr_setpshared", my_pthread_mutexattr_setpshared}, ++ {"pthread_mutexattr_setpshared", _hybris_hook_pthread_mutexattr_setpshared}, + {"pthread_condattr_init", pthread_condattr_init}, + {"pthread_condattr_getpshared", pthread_condattr_getpshared}, + {"pthread_condattr_setpshared", pthread_condattr_setpshared}, + {"pthread_condattr_destroy", pthread_condattr_destroy}, +- {"pthread_cond_init", my_pthread_cond_init}, +- {"pthread_cond_destroy", my_pthread_cond_destroy}, +- {"pthread_cond_broadcast", my_pthread_cond_broadcast}, +- {"pthread_cond_signal", my_pthread_cond_signal}, +- {"pthread_cond_wait", my_pthread_cond_wait}, +- {"pthread_cond_timedwait", my_pthread_cond_timedwait}, +- {"pthread_cond_timedwait_monotonic", my_pthread_cond_timedwait}, +- {"pthread_cond_timedwait_monotonic_np", my_pthread_cond_timedwait}, +- {"pthread_cond_timedwait_relative_np", my_pthread_cond_timedwait_relative_np}, ++ {"pthread_condattr_getclock", pthread_condattr_getclock}, ++ {"pthread_condattr_setclock", pthread_condattr_setclock}, ++ {"pthread_cond_init", _hybris_hook_pthread_cond_init}, ++ {"pthread_cond_destroy", _hybris_hook_pthread_cond_destroy}, ++ {"pthread_cond_broadcast", _hybris_hook_pthread_cond_broadcast}, ++ {"pthread_cond_signal", _hybris_hook_pthread_cond_signal}, ++ {"pthread_cond_wait", _hybris_hook_pthread_cond_wait}, ++ {"pthread_cond_timedwait", _hybris_hook_pthread_cond_timedwait}, ++ {"pthread_cond_timedwait_monotonic", _hybris_hook_pthread_cond_timedwait}, ++ {"pthread_cond_timedwait_monotonic_np", _hybris_hook_pthread_cond_timedwait}, ++ {"pthread_cond_timedwait_relative_np", _hybris_hook_pthread_cond_timedwait_relative_np}, + {"pthread_key_delete", pthread_key_delete}, +- {"pthread_setname_np", pthread_setname_np}, ++ {"pthread_setname_np", _hybris_hook_pthread_setname_np}, + {"pthread_once", pthread_once}, + {"pthread_key_create", pthread_key_create}, +- {"pthread_setspecific", pthread_setspecific}, +- {"pthread_getspecific", pthread_getspecific}, +- {"pthread_attr_init", my_pthread_attr_init}, +- {"pthread_attr_destroy", my_pthread_attr_destroy}, +- {"pthread_attr_setdetachstate", my_pthread_attr_setdetachstate}, +- {"pthread_attr_getdetachstate", my_pthread_attr_getdetachstate}, +- {"pthread_attr_setschedpolicy", my_pthread_attr_setschedpolicy}, +- {"pthread_attr_getschedpolicy", my_pthread_attr_getschedpolicy}, +- {"pthread_attr_setschedparam", my_pthread_attr_setschedparam}, +- {"pthread_attr_getschedparam", my_pthread_attr_getschedparam}, +- {"pthread_attr_setstacksize", my_pthread_attr_setstacksize}, +- {"pthread_attr_getstacksize", my_pthread_attr_getstacksize}, +- {"pthread_attr_setstackaddr", my_pthread_attr_setstackaddr}, +- {"pthread_attr_getstackaddr", my_pthread_attr_getstackaddr}, +- {"pthread_attr_setstack", my_pthread_attr_setstack}, +- {"pthread_attr_getstack", my_pthread_attr_getstack}, +- {"pthread_attr_setguardsize", my_pthread_attr_setguardsize}, +- {"pthread_attr_getguardsize", my_pthread_attr_getguardsize}, +- {"pthread_attr_setscope", my_pthread_attr_setscope}, +- {"pthread_attr_setscope", my_pthread_attr_getscope}, +- {"pthread_getattr_np", my_pthread_getattr_np}, +- {"pthread_rwlockattr_init", my_pthread_rwlockattr_init}, +- {"pthread_rwlockattr_destroy", my_pthread_rwlockattr_destroy}, +- {"pthread_rwlockattr_setpshared", my_pthread_rwlockattr_setpshared}, +- {"pthread_rwlockattr_getpshared", my_pthread_rwlockattr_getpshared}, +- {"pthread_rwlock_init", my_pthread_rwlock_init}, +- {"pthread_rwlock_destroy", my_pthread_rwlock_destroy}, +- {"pthread_rwlock_unlock", my_pthread_rwlock_unlock}, +- {"pthread_rwlock_wrlock", my_pthread_rwlock_wrlock}, +- {"pthread_rwlock_rdlock", my_pthread_rwlock_rdlock}, +- {"pthread_rwlock_tryrdlock", my_pthread_rwlock_tryrdlock}, +- {"pthread_rwlock_trywrlock", my_pthread_rwlock_trywrlock}, +- {"pthread_rwlock_timedrdlock", my_pthread_rwlock_timedrdlock}, +- {"pthread_rwlock_timedwrlock", my_pthread_rwlock_timedwrlock}, ++ {"pthread_setspecific", _hybris_hook_pthread_setspecific}, ++ {"pthread_getspecific", _hybris_hook_pthread_getspecific}, ++ {"pthread_attr_init", _hybris_hook_pthread_attr_init}, ++ {"pthread_attr_destroy", _hybris_hook_pthread_attr_destroy}, ++ {"pthread_attr_setdetachstate", _hybris_hook_pthread_attr_setdetachstate}, ++ {"pthread_attr_getdetachstate", _hybris_hook_pthread_attr_getdetachstate}, ++ {"pthread_attr_setschedpolicy", _hybris_hook_pthread_attr_setschedpolicy}, ++ {"pthread_attr_getschedpolicy", _hybris_hook_pthread_attr_getschedpolicy}, ++ {"pthread_attr_setschedparam", _hybris_hook_pthread_attr_setschedparam}, ++ {"pthread_attr_getschedparam", _hybris_hook_pthread_attr_getschedparam}, ++ {"pthread_attr_setstacksize", _hybris_hook_pthread_attr_setstacksize}, ++ {"pthread_attr_getstacksize", _hybris_hook_pthread_attr_getstacksize}, ++ {"pthread_attr_setstackaddr", _hybris_hook_pthread_attr_setstackaddr}, ++ {"pthread_attr_getstackaddr", _hybris_hook_pthread_attr_getstackaddr}, ++ {"pthread_attr_setstack", _hybris_hook_pthread_attr_setstack}, ++ {"pthread_attr_getstack", _hybris_hook_pthread_attr_getstack}, ++ {"pthread_attr_setguardsize", _hybris_hook_pthread_attr_setguardsize}, ++ {"pthread_attr_getguardsize", _hybris_hook_pthread_attr_getguardsize}, ++ {"pthread_attr_setscope", _hybris_hook_pthread_attr_setscope}, ++ {"pthread_attr_getscope", _hybris_hook_pthread_attr_getscope}, ++ {"pthread_getattr_np", _hybris_hook_pthread_getattr_np}, ++ {"pthread_rwlockattr_init", _hybris_hook_pthread_rwlockattr_init}, ++ {"pthread_rwlockattr_destroy", _hybris_hook_pthread_rwlockattr_destroy}, ++ {"pthread_rwlockattr_setpshared", _hybris_hook_pthread_rwlockattr_setpshared}, ++ {"pthread_rwlockattr_getpshared", _hybris_hook_pthread_rwlockattr_getpshared}, ++ {"pthread_rwlock_init", _hybris_hook_pthread_rwlock_init}, ++ {"pthread_rwlock_destroy", _hybris_hook_pthread_rwlock_destroy}, ++ {"pthread_rwlock_unlock", _hybris_hook_pthread_rwlock_unlock}, ++ {"pthread_rwlock_wrlock", _hybris_hook_pthread_rwlock_wrlock}, ++ {"pthread_rwlock_rdlock", _hybris_hook_pthread_rwlock_rdlock}, ++ {"pthread_rwlock_tryrdlock", _hybris_hook_pthread_rwlock_tryrdlock}, ++ {"pthread_rwlock_trywrlock", _hybris_hook_pthread_rwlock_trywrlock}, ++ {"pthread_rwlock_timedrdlock", _hybris_hook_pthread_rwlock_timedrdlock}, ++ {"pthread_rwlock_timedwrlock", _hybris_hook_pthread_rwlock_timedwrlock}, ++ /* bionic-only pthread */ ++ {"__pthread_gettid", _hybris_hook_pthread_gettid}, ++ {"pthread_gettid_np", _hybris_hook_pthread_gettid}, + /* stdio.h */ +- {"__isthreaded", &__my_isthreaded}, +- {"__sF", &my_sF}, ++ {"__isthreaded", &___hybris_hook_isthreaded}, ++ {"__sF", &_hybris_hook_sF}, + {"fopen", fopen}, + {"fdopen", fdopen}, + {"popen", popen}, +@@ -1489,79 +2459,80 @@ static struct _hook hooks[] = { + {"snprintf", snprintf}, + {"vsprintf", vsprintf}, + {"vsnprintf", vsnprintf}, +- {"clearerr", my_clearerr}, +- {"fclose", my_fclose}, +- {"feof", my_feof}, +- {"ferror", my_ferror}, +- {"fflush", my_fflush}, +- {"fgetc", my_fgetc}, +- {"fgetpos", my_fgetpos}, +- {"fgets", my_fgets}, +- {"fprintf", my_fprintf}, +- {"fputc", my_fputc}, +- {"fputs", my_fputs}, +- {"fread", my_fread}, +- {"freopen", my_freopen}, +- {"fscanf", my_fscanf}, +- {"fseek", my_fseek}, +- {"fseeko", my_fseeko}, +- {"fsetpos", my_fsetpos}, +- {"ftell", my_ftell}, +- {"ftello", my_ftello}, +- {"fwrite", my_fwrite}, +- {"getc", my_getc}, +- {"getdelim", my_getdelim}, +- {"getline", my_getline}, +- {"putc", my_putc}, +- {"rewind", my_rewind}, +- {"setbuf", my_setbuf}, +- {"setvbuf", my_setvbuf}, +- {"ungetc", my_ungetc}, ++ {"clearerr", _hybris_hook_clearerr}, ++ {"fclose", _hybris_hook_fclose}, ++ {"feof", _hybris_hook_feof}, ++ {"ferror", _hybris_hook_ferror}, ++ {"fflush", _hybris_hook_fflush}, ++ {"fgetc", _hybris_hook_fgetc}, ++ {"fgetpos", _hybris_hook_fgetpos}, ++ {"fgets", _hybris_hook_fgets}, ++ {"fprintf", _hybris_hook_fprintf}, ++ {"fputc", _hybris_hook_fputc}, ++ {"fputs", _hybris_hook_fputs}, ++ {"fread", _hybris_hook_fread}, ++ {"freopen", _hybris_hook_freopen}, ++ {"fscanf", _hybris_hook_fscanf}, ++ {"fseek", _hybris_hook_fseek}, ++ {"fseeko", _hybris_hook_fseeko}, ++ {"fsetpos", _hybris_hook_fsetpos}, ++ {"ftell", _hybris_hook_ftell}, ++ {"ftello", _hybris_hook_ftello}, ++ {"fwrite", _hybris_hook_fwrite}, ++ {"getc", _hybris_hook_getc}, ++ {"getdelim", _hybris_hook_getdelim}, ++ {"getline", _hybris_hook_getline}, ++ {"putc", _hybris_hook_putc}, ++ {"rewind", _hybris_hook_rewind}, ++ {"setbuf", _hybris_hook_setbuf}, ++ {"setvbuf", _hybris_hook_setvbuf}, ++ {"ungetc", _hybris_hook_ungetc}, + {"vasprintf", vasprintf}, +- {"vfprintf", my_vfprintf}, +- {"vfscanf", my_vfscanf}, +- {"fileno", my_fileno}, +- {"pclose", my_pclose}, +- {"flockfile", my_flockfile}, +- {"ftrylockfile", my_ftrylockfile}, +- {"funlockfile", my_funlockfile}, +- {"getc_unlocked", my_getc_unlocked}, +- {"putc_unlocked", my_putc_unlocked}, +- //{"fgetln", my_fgetln}, +- {"fpurge", my_fpurge}, +- {"getw", my_getw}, +- {"putw", my_putw}, +- {"setbuffer", my_setbuffer}, +- {"setlinebuf", my_setlinebuf}, ++ {"vfprintf", _hybris_hook_vfprintf}, ++ {"vfscanf", _hybris_hook_vfscanf}, ++ {"fileno", _hybris_hook_fileno}, ++ {"pclose", _hybris_hook_pclose}, ++ {"flockfile", _hybris_hook_flockfile}, ++ {"ftrylockfile", _hybris_hook_ftrylockfile}, ++ {"funlockfile", _hybris_hook_funlockfile}, ++ {"getc_unlocked", _hybris_hook_getc_unlocked}, ++ {"putc_unlocked", _hybris_hook_putc_unlocked}, ++ //{"fgetln", _hybris_hook_fgetln}, ++ {"fpurge", _hybris_hook_fpurge}, ++ {"getw", _hybris_hook_getw}, ++ {"putw", _hybris_hook_putw}, ++ {"setbuffer", _hybris_hook_setbuffer}, ++ {"setlinebuf", _hybris_hook_setlinebuf}, + {"__errno", __errno_location}, +- {"__set_errno", my_set_errno}, ++ {"__set_errno", _hybris_hook_set_errno}, + /* net specifics, to avoid __res_get_state */ +- {"getaddrinfo", getaddrinfo}, ++ {"getaddrinfo", _hybris_hook_getaddrinfo}, ++ {"freeaddrinfo", _hybris_hook_freeaddrinfo}, + {"gethostbyaddr", gethostbyaddr}, + {"gethostbyname", gethostbyname}, + {"gethostbyname2", gethostbyname2}, + {"gethostent", gethostent}, + {"strftime", strftime}, +- {"sysconf", my_sysconf}, +- {"dlopen", android_dlopen}, +- {"dlerror", android_dlerror}, +- {"dlsym", android_dlsym}, +- {"dladdr", android_dladdr}, +- {"dlclose", android_dlclose}, ++ {"sysconf", _hybris_hook_sysconf}, ++ {"dlopen", _hybris_hook_android_dlopen}, ++ {"dlerror", _hybris_hook_android_dlerror}, ++ {"dlsym", _hybris_hook_android_dlsym}, ++ {"dladdr", _hybris_hook_android_dladdr}, ++ {"dlclose", _hybris_hook_android_dlclose}, + /* dirent.h */ + {"opendir", opendir}, + {"fdopendir", fdopendir}, + {"closedir", closedir}, +- {"readdir", my_readdir}, +- {"readdir_r", my_readdir_r}, ++ {"readdir", _hybris_hook_readdir}, ++ {"readdir_r", _hybris_hook_readdir_r}, + {"rewinddir", rewinddir}, + {"seekdir", seekdir}, + {"telldir", telldir}, + {"dirfd", dirfd}, + /* fcntl.h */ +- {"open", my_open}, ++ {"open", _hybris_hook_open}, + // TODO: scandir, scandirat, alphasort, versionsort +- {"__get_tls_hooks", __get_tls_hooks}, ++ {"__get_tls_hooks", _hybris_hook_get_tls_hooks}, + {"sscanf", sscanf}, + {"scanf", scanf}, + {"vscanf", vscanf}, +@@ -1575,6 +2546,9 @@ static struct _hook hooks[] = { + {"timer_gettime", timer_gettime}, + {"timer_delete", timer_delete}, + {"timer_getoverrun", timer_getoverrun}, ++ {"localtime", localtime}, ++ {"localtime_r", localtime_r}, ++ {"gmtime", gmtime}, + {"abort", abort}, + {"writev", writev}, + /* unistd.h */ +@@ -1583,34 +2557,372 @@ static struct _hook hooks[] = { + {"getgrgid", getgrgid}, + {"__cxa_atexit", __cxa_atexit}, + {"__cxa_finalize", __cxa_finalize}, +- {NULL, NULL}, ++ {"__system_property_read", ___hybris_hook_system_property_read}, ++ {"__system_property_set", property_set}, ++ {"__system_property_foreach", ___hybris_hook_system_property_foreach}, ++ {"__system_property_find", ___hybris_hook_system_property_find}, ++ {"__system_property_serial", ___hybris_hook_system_property_serial}, ++ {"__system_property_wait", ___hybris_hook_system_property_wait}, ++ {"__system_property_update", ___hybris_hook_system_property_update}, ++ {"__system_property_add", ___hybris_hook_system_property_add}, ++ {"__system_property_wait_any", ___hybris_hook_system_property_wait_any}, ++ {"__system_property_find_nth", ___hybris_hook_system_property_find_nth}, ++ /* sys/prctl.h */ ++ {"prctl", _hybris_hook_prctl}, ++}; ++ ++static struct _hook hooks_mm[] = { ++ {"strtol", _hybris_hook_strtol}, ++ {"strlcat",strlcat}, ++ {"strlcpy",strlcpy}, ++ {"setenv", _hybris_hook_setenv}, ++ {"putenv", _hybris_hook_putenv}, ++ {"clearenv", _hybris_hook_clearenv}, ++ {"dprintf", dprintf}, ++ {"mallinfo", mallinfo}, ++ {"malloc_usable_size", _hybris_hook_malloc_usable_size}, ++ {"posix_memalign", _hybris_hook_posix_memalign}, ++ {"mprotect", _hybris_hook_mprotect}, ++ {"__memcpy_chk", __memcpy_chk}, ++ {"__memset_chk", __memset_chk}, ++ {"__gnu_strerror_r",_hybris_hook__gnu_strerror_r}, ++ {"__strncpy_chk",__strncpy_chk}, ++ {"pthread_rwlockattr_getkind_np", _hybris_hook_pthread_rwlockattr_getkind_np}, ++ {"pthread_rwlockattr_setkind_np", _hybris_hook_pthread_rwlockattr_setkind_np}, ++ /* unistd.h */ ++ {"fork", _hybris_hook_fork}, ++ {"ttyname", ttyname}, ++ {"swprintf", swprintf}, ++ {"fmemopen", fmemopen}, ++ {"open_memstream", open_memstream}, ++ {"open_wmemstream", open_wmemstream}, ++ {"ptsname", ptsname}, ++ {"__hybris_set_errno_internal", _hybris_hook_set_errno}, ++ {"getservbyname", getservbyname}, ++ {"scandir", scandir}, ++ {"scandir64", scandir64}, ++ /* libgen.h */ ++ {"basename", _hybris_hook_basename}, ++ {"dirname", _hybris_hook_dirname}, ++ /* locale.h */ ++ {"newlocale", _hybris_hook_newlocale}, ++ {"freelocale", _hybris_hook_freelocale}, ++ {"duplocale", _hybris_hook_duplocale}, ++ {"uselocale", _hybris_hook_uselocale}, ++ {"localeconv", _hybris_hook_localeconv}, ++ {"setlocale", _hybris_hook_setlocale}, ++ /* sys/mman.h */ ++ {"mmap", _hybris_hook_mmap}, ++ {"munmap", _hybris_hook_munmap}, ++ /* wchar.h */ ++ {"wmemchr", wmemchr}, ++ {"wmemcmp", wmemcmp}, ++ {"wmemcpy", wmemcpy}, ++ {"wmemmove", wmemmove}, ++ {"wmemset", wmemset}, ++ {"wmempcpy", wmempcpy}, ++ {"fputws", _hybris_hook_fputws}, ++ // It's enough to hook vfwprintf here as fwprintf will call it with a ++ // proper va_list in place so we don't have to handle this here. ++ {"vfwprintf", _hybris_hook_vfwprintf}, ++ {"fputwc", _hybris_hook_fputwc}, ++ {"putwc", _hybris_hook_putwc}, ++ {"fgetwc", _hybris_hook_fgetwc}, ++ {"getwc", _hybris_hook_getwc}, ++ /* sched.h */ ++ {"clone", clone}, ++ /* mntent.h */ ++ {"setmntent", _hybris_hook_setmntent}, ++ {"getmntent", _hybris_hook_getmntent}, ++ {"getmntent_r", _hybris_hook_getmntent_r}, ++ {"endmntent", _hybris_hook_endmntent}, ++ /* stdlib.h */ ++ {"system", system}, ++ /* pwd.h */ ++ {"getgrnam", getgrnam}, ++ {"getpwuid", getpwuid}, ++ {"getpwnam", getpwnam}, ++ /* signal.h */ ++ /* Hooks commented out for the moment as we need proper translations between ++ * bionic and glibc types for them to work (for instance, sigset_t has ++ * different definitions in each library). ++ */ ++#if 0 ++ {"sigaction", sigaction}, ++ {"sigaddset", sigaddset}, ++ {"sigaltstack", sigaltstack}, ++ {"sigblock", sigblock}, ++ {"sigdelset", sigdelset}, ++ {"sigemptyset", sigemptyset}, ++ {"sigfillset", sigfillset}, ++ {"siginterrupt", siginterrupt}, ++ {"sigismember", sigismember}, ++ {"siglongjmp", siglongjmp}, ++ {"signal", signal}, ++ {"signalfd", signalfd}, ++ {"sigpending", sigpending}, ++ {"sigprocmask", sigprocmask}, ++ {"sigqueue", sigqueue}, ++ // setjmp.h defines segsetjmp via a #define and the real symbol ++ // we have to forward to is __sigsetjmp ++ {"sigsetjmp", __sigsetjmp}, ++ {"sigsetmask", sigsetmask}, ++ {"sigsuspend", sigsuspend}, ++ {"sigtimedwait", sigtimedwait}, ++ {"sigwait", sigwait}, ++ {"sigwaitinfo", sigwaitinfo}, ++#endif ++ /* dirent.h */ ++ {"scandir", _hybris_hook_scandir}, ++ {"scandirat", _hybris_hook_scandirat}, ++ {"alphasort,", _hybris_hook_alphasort}, ++ {"versionsort,", _hybris_hook_versionsort}, ++ {"scandir64", scandir}, + }; + +-void *get_hooked_symbol(char *sym) ++ ++static int hook_cmp(const void *a, const void *b) ++{ ++ return strcmp(((struct _hook*)a)->name, ((struct _hook*)b)->name); ++} ++ ++void hybris_set_hook_callback(hybris_hook_cb callback) ++{ ++ hook_callback = callback; ++} ++ ++static int get_android_sdk_version() + { +- struct _hook *ptr = &hooks[0]; ++ static int sdk_version = -1; ++ ++ if (sdk_version > 0) ++ return sdk_version; ++ ++ char value[PROP_VALUE_MAX]; ++ property_get("ro.build.version.sdk", value, "19"); ++ ++ sdk_version = 19; ++ if (strlen(value) > 0) ++ sdk_version = atoi(value); ++ ++#ifdef UBUNTU_LINKER_OVERRIDES ++ /* We override both frieza and turbo here until they are ready to be ++ * upgraded to the newer linker. */ ++ char device_name[PROP_VALUE_MAX]; ++ memset(device_name, 0, sizeof(device_name)); ++ property_get("ro.build.product", device_name, ""); ++ if (strlen(device_name) > 0) { ++ /* Force SDK version for both frieza/cooler and turbo for the time being */ ++ if (strcmp(device_name, "frieza") == 0 || ++ strcmp(device_name, "cooler") == 0 || ++ strcmp(device_name, "turbo") == 0) ++ sdk_version = 19; ++ } ++#endif ++ ++ char *version_override = getenv("HYBRIS_ANDROID_SDK_VERSION"); ++ if (version_override) ++ sdk_version = atoi(version_override); ++ ++ LOGD("Using SDK API version %i\n", sdk_version); ++ ++ return sdk_version; ++} ++ ++#define HOOKS_SIZE(hooks) \ ++ (sizeof(hooks) / sizeof(hooks[0])) ++ ++ ++static void* __hybris_get_hooked_symbol(const char *sym, const char *requester) ++{ ++ static int sorted = 0; + static int counter = -1; ++ void *found = NULL; ++ struct _hook key; + +- while (ptr->name != NULL) ++ /* First check if we have a callback registered which could ++ * give us a context specific hook implementation */ ++ if (hook_callback) + { +- if (strcmp(sym, ptr->name) == 0){ +- return ptr->func; +- } +- ptr++; ++ found = hook_callback(sym, requester); ++ if (found) ++ return (void*) found; + } +- if (strstr(sym, "pthread") != NULL) ++ ++ if (!sorted) ++ { ++ qsort(hooks_common, HOOKS_SIZE(hooks_common), sizeof(hooks_common[0]), hook_cmp); ++ qsort(hooks_mm, HOOKS_SIZE(hooks_mm), sizeof(hooks_mm[0]), hook_cmp); ++ sorted = 1; ++ } ++ ++ /* Allow newer hooks to override those which are available for all versions */ ++ key.name = sym; ++ if (get_android_sdk_version() > 21) ++ found = bsearch(&key, hooks_mm, HOOKS_SIZE(hooks_mm), sizeof(hooks_mm[0]), hook_cmp); ++ if (!found) ++ found = bsearch(&key, hooks_common, HOOKS_SIZE(hooks_common), sizeof(hooks_common[0]), hook_cmp); ++ ++ if (found) ++ return ((struct _hook*) found)->func; ++ ++ if (strncmp(sym, "pthread", 7) == 0 || ++ strncmp(sym, "__pthread", 9) == 0) + { + /* safe */ + if (strcmp(sym, "pthread_sigmask") == 0) + return NULL; + /* not safe */ + counter--; +- LOGD("%s %i\n", sym, counter); ++ // If you're experiencing a crash later on check the address of the ++ // function pointer being call. If it matches the printed counter ++ // value here then you can easily find out which symbol is missing. ++ LOGD("Missing hook for pthread symbol %s (counter %i)\n", sym, counter); + return (void *) counter; + } ++ ++ if (!getenv("HYBRIS_DONT_PRINT_SYMBOLS_WITHOUT_HOOK")) ++ LOGD("Could not find a hook for symbol %s", sym); ++ + return NULL; + } + +-void android_linker_init() ++static void *linker_handle = NULL; ++ ++static void* __hybris_load_linker(const char *path) ++{ ++ void *handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); ++ if (!handle) { ++ fprintf(stderr, "ERROR: Failed to load hybris linker for Android SDK version %d\n", ++ get_android_sdk_version()); ++ return NULL; ++ } ++ return handle; ++} ++ ++#define LINKER_NAME_JB "jb" ++#define LINKER_NAME_MM "mm" ++ ++#if defined(WANT_LINKER_JB) ++#define LINKER_NAME_DEFAULT LINKER_NAME_JB ++#elif defined(WANT_LINKER_MM) ++#define LINKER_NAME_DEFAULT LINKER_NAME_MM ++#endif ++ ++static int linker_initialized = 0; ++ ++static void __hybris_linker_init() ++{ ++ LOGD("Linker initialization"); ++ ++ int sdk_version = get_android_sdk_version(); ++ ++ char path[PATH_MAX]; ++ const char *name = LINKER_NAME_DEFAULT; ++ ++ /* 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_MM) ++ if (sdk_version <= 23) ++ name = LINKER_NAME_MM; ++#endif ++#if defined(WANT_LINKER_JB) ++ if (sdk_version < 21) ++ name = LINKER_NAME_JB; ++#endif ++ ++ const char *linker_dir = LINKER_PLUGIN_DIR; ++ const char *user_linker_dir = getenv("HYBRIS_LINKER_DIR"); ++ if (user_linker_dir) ++ linker_dir = user_linker_dir; ++ ++ snprintf(path, PATH_MAX, "%s/%s.so", linker_dir, name); ++ ++ LOGD("Loading linker from %s..", path); ++ ++ linker_handle = __hybris_load_linker(path); ++ if (!linker_handle) ++ exit(1); ++ ++ /* Load all necessary symbols we need from the linker */ ++ _android_linker_init = dlsym(linker_handle, "android_linker_init"); ++ _android_dlopen = dlsym(linker_handle, "android_dlopen"); ++ _android_dlsym = dlsym(linker_handle, "android_dlsym"); ++ _android_dladdr = dlsym(linker_handle, "android_dladdr"); ++ _android_dlclose = dlsym(linker_handle, "android_dlclose"); ++ _android_dlerror = dlsym(linker_handle, "android_dlerror"); ++ ++ /* Now its time to setup the linker itself */ ++ _android_linker_init(sdk_version, __hybris_get_hooked_symbol); ++ ++ linker_initialized = 1; ++} ++ ++#define ENSURE_LINKER_IS_LOADED() \ ++ if (!linker_initialized) \ ++ __hybris_linker_init(); ++ ++/* NOTE: As we're not linking directly with the linker anymore ++ * but several users are using android_* functions directly we ++ * have to export them here. */ ++ ++void *android_dlopen(const char *filename, int flag) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlopen) ++ return NULL; ++ ++ return _android_dlopen(filename,flag); ++} ++ ++void *android_dlsym(void *handle, const char *symbol) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlsym) ++ return NULL; ++ ++ return _android_dlsym(handle,symbol); ++} ++ ++int android_dlclose(void *handle) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlclose) ++ return -1; ++ ++ return _android_dlclose(handle); ++} ++ ++const char *android_dlerror(void) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlerror) ++ return NULL; ++ ++ return _android_dlerror(); ++} ++ ++void *hybris_dlopen(const char *filename, int flag) ++{ ++ return android_dlopen(filename,flag); ++} ++ ++void *hybris_dlsym(void *handle, const char *symbol) ++{ ++ return android_dlsym(handle,symbol); ++} ++ ++int hybris_dlclose(void *handle) ++{ ++ return android_dlclose(handle); ++} ++ ++const char *hybris_dlerror(void) + { ++ return android_dlerror(); + } +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks_shm.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks_shm.c +@@ -123,7 +123,9 @@ static void _hybris_shm_init() + else { + LOGD("Creating a new shared memory segment."); + +- _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0660); ++ mode_t pumask = umask(0); ++ _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0666); ++ umask(pumask); + if (_hybris_shm_fd >= 0) { + ftruncate( _hybris_shm_fd, size_to_map ); + /* Map the memory object */ +@@ -171,11 +173,12 @@ static void _hybris_shm_extend_region() + + /* + * Determine if the pointer that has been extracted by hybris is +- * pointing to an address in the shared memory ++ * pointing to an address in the shared memory. + */ + int hybris_is_pointer_in_shm(void *ptr) + { +- if ((unsigned int)ptr >= HYBRIS_SHM_MASK) ++ if (((unsigned int) ptr >= HYBRIS_SHM_MASK) && ++ ((unsigned int) ptr <= HYBRIS_SHM_MASK_TOP)) + return 1; + + return 0; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks_shm.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks_shm.h +@@ -20,6 +20,9 @@ + + #include + ++/* Leave space to workaround the issue that Android might pass negative int values */ ++#define HYBRIS_SHM_MASK_TOP 0xFFFFFFF0UL ++ + typedef unsigned int hybris_shm_pointer_t; + + /* +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/Makefile.am +@@ -6,26 +6,28 @@ if WANT_ARCH_X86 + ARCHFLAGS = -DANDROID_X86_LINKER + endif + +-noinst_LTLIBRARIES = \ +- libandroid-linker.la +-libandroid_linker_la_SOURCES = \ ++modlibexecdir = $(libdir)/libhybris/linker ++modlibexec_LTLIBRARIES = jb.la ++jb_la_SOURCES = \ + dlfcn.c \ + linker.c \ + linker_environ.c \ + linker_format.c \ +- rt.c +-libandroid_linker_la_CFLAGS = \ ++ rt.c \ ++ ../strlcpy.c ++jb_la_CFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ + -I$(top_srcdir)/common \ + -D_GNU_SOURCE \ +- -DLINKER_TEXT_BASE=0xB0000100 \ +- -DLINKER_AREA_SIZE=0x01000000 \ + -DDEFAULT_HYBRIS_LD_LIBRARY_PATH="\"@DEFAULT_HYBRIS_LD_LIBRARY_PATH@\"" \ + $(ARCHFLAGS) ++jb_la_LDFLAGS = \ ++ -module \ ++ -avoid-version + + if WANT_DEBUG +-libandroid_linker_la_CFLAGS += -DLINKER_DEBUG=1 ++jb_la_CFLAGS += -DLINKER_DEBUG=1 + else +-libandroid_linker_la_CFLAGS += -DLINKER_DEBUG=0 ++jb_la_CFLAGS += -DLINKER_DEBUG=0 + endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/dlfcn.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/dlfcn.c +@@ -78,7 +78,7 @@ const char *android_dlerror(void) + void *android_dlsym(void *handle, const char *symbol) + { + soinfo *found; +- Elf32_Sym *sym; ++ Elf_Sym *sym; + unsigned bind; + + pthread_mutex_lock(&dl_lock); +@@ -142,7 +142,7 @@ int android_dladdr(const void *addr, Dl_ + info->dli_fbase = (void*)si->base; + + /* Determine if any symbol in the library contains the specified address */ +- Elf32_Sym *sym = find_containing_symbol(addr, si); ++ Elf_Sym *sym = find_containing_symbol(addr, si); + + if(sym != NULL) { + info->dli_sname = si->strtab + sym->st_name; +@@ -171,7 +171,7 @@ int android_dl_iterate_phdr(int (*cb)(st + // 0000000 00011111 111112 22222222 2333333 333344444444445555555 + // 0123456 78901234 567890 12345678 9012345 678901234567890123456 + #define ANDROID_LIBDL_STRTAB \ +- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0dl_iterate_phdr\0" ++ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0dl_unwind_find_exidx\0" + + _Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); + +@@ -191,7 +191,7 @@ _Unwind_Ptr android_dl_unwind_find_exidx + #endif + + +-static Elf32_Sym libdl_symtab[] = { ++static Elf_Sym libdl_symtab[] = { + // total length of libdl_info.strtab, including trailing 0 + // This is actually the the STH_UNDEF entry. Technically, it's + // supposed to have st_name == 0, but instead, it points to an index +@@ -199,44 +199,42 @@ static Elf32_Sym libdl_symtab[] = { + { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, + }, + { st_name: 0, // starting index of the name in libdl_info.strtab +- st_value: (Elf32_Addr) &android_dlopen, ++ st_value: (Elf_Addr) &android_dlopen, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 7, +- st_value: (Elf32_Addr) &android_dlclose, ++ st_value: (Elf_Addr) &android_dlclose, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 15, +- st_value: (Elf32_Addr) &android_dlsym, ++ st_value: (Elf_Addr) &android_dlsym, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 21, +- st_value: (Elf32_Addr) &android_dlerror, ++ st_value: (Elf_Addr) &android_dlerror, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 29, +- st_value: (Elf32_Addr) &android_dladdr, ++ st_value: (Elf_Addr) &android_dladdr, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +-#ifdef ANDROID_ARM_LINKER + { st_name: 36, +- st_value: (Elf32_Addr) &android_dl_unwind_find_exidx, ++ st_value: (Elf_Addr) &android_dl_iterate_phdr, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +- { st_name: 57, +-#else +- { st_name: 36, +-#endif +- st_value: (Elf32_Addr) &android_dl_iterate_phdr, ++#ifdef ANDROID_ARM_LINKER ++ { st_name: 52, ++ st_value: (Elf_Addr) &android_dl_unwind_find_exidx, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, ++#endif + }; + + /* Fake out a hash table with a single bucket. +@@ -273,12 +271,8 @@ soinfo libdl_info = { + symtab: libdl_symtab, + + refcount: 1, +- nbucket: 1, +-#if defined(ANDROID_ARM_LINKER) +- nchain: 8, +-#else +- nchain: 7, +-#endif ++ nbucket: sizeof(libdl_buckets)/sizeof(unsigned), ++ nchain: sizeof(libdl_chains)/sizeof(unsigned), + bucket: libdl_buckets, + chain: libdl_chains, + }; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.c +@@ -79,6 +79,7 @@ + * having a hard limit (64) + */ + ++static void* (*_get_hooked_symbol)(const char *symbol, const char *requester); + + static int link_image(soinfo *si, unsigned wr_offset); + +@@ -380,10 +381,10 @@ android_dl_iterate_phdr(int (*cb)(struct + return rv; + } + +-static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) ++static Elf_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) + { +- Elf32_Sym *s; +- Elf32_Sym *symtab = si->symtab; ++ Elf_Sym *s; ++ Elf_Sym *symtab = si->symtab; + const char *strtab = si->strtab; + unsigned n; + +@@ -425,11 +426,11 @@ static unsigned elfhash(const char *_nam + return h; + } + +-static Elf32_Sym * ++static Elf_Sym * + _do_lookup(soinfo *si, const char *name, unsigned *base) + { + unsigned elf_hash = elfhash(name); +- Elf32_Sym *s; ++ Elf_Sym *s; + unsigned *d; + soinfo *lsi = si; + int i; +@@ -501,17 +502,17 @@ done: + /* This is used by dl_sym(). It performs symbol lookup only within the + specified soinfo object and not in any of its dependencies. + */ +-Elf32_Sym *lookup_in_library(soinfo *si, const char *name) ++Elf_Sym *lookup_in_library(soinfo *si, const char *name) + { + return _elf_lookup(si, elfhash(name), name); + } + + /* This is used by dl_sym(). It performs a global symbol lookup. + */ +-Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) ++Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start) + { + unsigned elf_hash = elfhash(name); +- Elf32_Sym *s = NULL; ++ Elf_Sym *s = NULL; + soinfo *si; + + if(start == NULL) { +@@ -552,7 +553,7 @@ soinfo *find_containing_library(const vo + return NULL; + } + +-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) ++Elf_Sym *find_containing_symbol(const void *addr, soinfo *si) + { + unsigned int i; + unsigned soaddr = (unsigned)addr - si->base; +@@ -560,7 +561,7 @@ Elf32_Sym *find_containing_symbol(const + /* Search the library's symbol table for any defined symbol which + * contains this address */ + for(i=0; inchain; i++) { +- Elf32_Sym *sym = &si->symtab[i]; ++ Elf_Sym *sym = &si->symtab[i]; + + if(sym->st_shndx != SHN_UNDEF && + soaddr >= sym->st_value && +@@ -575,7 +576,7 @@ Elf32_Sym *find_containing_symbol(const + #if 0 + static void dump(soinfo *si) + { +- Elf32_Sym *s = si->symtab; ++ Elf_Sym *s = si->symtab; + unsigned n; + + for(n = 0; n < si->nchain; n++) { +@@ -704,7 +705,7 @@ is_prelinked(int fd, const char *name) + static int + verify_elf_object(void *base, const char *name) + { +- Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; ++ Elf_Ehdr *hdr = (Elf_Ehdr *) base; + + if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; + if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; +@@ -749,8 +750,8 @@ get_lib_extents(int fd, const char *name + unsigned min_vaddr = 0xffffffff; + unsigned max_vaddr = 0; + unsigned char *_hdr = (unsigned char *)__hdr; +- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; +- Elf32_Phdr *phdr; ++ Elf_Ehdr *ehdr = (Elf_Ehdr *)_hdr; ++ Elf_Phdr *phdr; + int cnt; + + TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); +@@ -769,7 +770,7 @@ get_lib_extents(int fd, const char *name + TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); + } + +- phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); ++ phdr = (Elf_Phdr *)(_hdr + ehdr->e_phoff); + + /* find the min/max p_vaddrs from all the PT_LOAD segments so we can + * get the range. */ +@@ -884,12 +885,12 @@ err: + static int + load_segments(int fd, void *header, soinfo *si) + { +- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; +- Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); +- Elf32_Addr base = (Elf32_Addr) si->base; ++ Elf_Ehdr *ehdr = (Elf_Ehdr *)header; ++ Elf_Phdr *phdr = (Elf_Phdr *)((unsigned char *)header + ehdr->e_phoff); ++ Elf_Addr base = (Elf_Addr) si->base; + int cnt; + unsigned len; +- Elf32_Addr tmp; ++ Elf_Addr tmp; + unsigned char *pbase; + unsigned char *extra_base; + unsigned extra_len; +@@ -955,7 +956,7 @@ load_segments(int fd, void *header, soin + * | | + * _+---------------------+ page boundary + */ +- tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & ++ tmp = (Elf_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & + (~PAGE_MASK)); + if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { + extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; +@@ -1019,7 +1020,7 @@ load_segments(int fd, void *header, soin + phdr->p_vaddr, phdr->p_memsz); + goto fail; + } +- si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr); ++ si->gnu_relro_start = (Elf_Addr) (base + phdr->p_vaddr); + si->gnu_relro_len = (unsigned) phdr->p_memsz; + } else { + #ifdef ANDROID_ARM_LINKER +@@ -1066,11 +1067,11 @@ fail: + */ + #if 0 + static unsigned +-get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) ++get_wr_offset(int fd, const char *name, Elf_Ehdr *ehdr) + { +- Elf32_Shdr *shdr_start; +- Elf32_Shdr *shdr; +- int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); ++ Elf_Shdr *shdr_start; ++ Elf_Shdr *shdr; ++ int shdr_sz = ehdr->e_shnum * sizeof(Elf_Shdr); + int cnt; + unsigned wr_offset = 0xffffffff; + +@@ -1103,7 +1104,7 @@ load_library(const char *name) + unsigned req_base; + const char *bname; + soinfo *si = NULL; +- Elf32_Ehdr *hdr; ++ Elf_Ehdr *hdr; + + if(fd == -1) { + DL_ERR("Library '%s' not found", name); +@@ -1160,8 +1161,8 @@ load_library(const char *name) + + /* this might not be right. Technically, we don't even need this info + * once we go through 'load_segments'. */ +- hdr = (Elf32_Ehdr *)si->base; +- si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); ++ hdr = (Elf_Ehdr *)si->base; ++ si->phdr = (Elf_Phdr *)((unsigned char *)si->base + hdr->e_phoff); + si->phnum = hdr->e_phnum; + /**/ + +@@ -1260,7 +1261,7 @@ unsigned unload_library(soinfo *si) + * in link_image. This is needed to undo the DT_NEEDED hack below. + */ + if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) { +- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); ++ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); + unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; + if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0) + DL_ERR("%5d %s: could not undo GNU_RELRO protections. " +@@ -1303,16 +1304,16 @@ unsigned unload_library(soinfo *si) + } + + /* TODO: don't use unsigned for addrs below. It works, but is not +- * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned ++ * ideal. They should probably be either uint32_t, Elf_Addr, or unsigned + * long. + */ +-static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) ++static int reloc_library(soinfo *si, Elf_Rel *rel, unsigned count) + { +- Elf32_Sym *symtab = si->symtab; ++ Elf_Sym *symtab = si->symtab; + const char *strtab = si->strtab; +- Elf32_Sym *s; ++ Elf_Sym *s; + unsigned base; +- Elf32_Rel *start = rel; ++ Elf_Rel *start = rel; + unsigned idx; + + for (idx = 0; idx < count; ++idx) { +@@ -1327,7 +1328,7 @@ static int reloc_library(soinfo *si, Elf + if(sym != 0) { + sym_name = (char *)(strtab + symtab[sym].st_name); + INFO("HYBRIS: '%s' checking hooks for sym '%s'\n", si->name, sym_name); +- sym_addr = get_hooked_symbol(sym_name); ++ sym_addr = _get_hooked_symbol(sym_name, si->name); + if (sym_addr != NULL) { + INFO("HYBRIS: '%s' hooked symbol %s to %x\n", si->name, + sym_name, sym_addr); +@@ -1711,7 +1712,7 @@ static int nullify_closed_stdio (void) + static int link_image(soinfo *si, unsigned wr_offset) + { + unsigned *d; +- Elf32_Phdr *phdr = si->phdr; ++ Elf_Phdr *phdr = si->phdr; + int phnum = si->phnum; + + INFO("[ %5d linking %s ]\n", pid, si->name); +@@ -1794,7 +1795,7 @@ static int link_image(soinfo *si, unsign + phdr->p_vaddr, phdr->p_memsz); + goto fail; + } +- si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr); ++ si->gnu_relro_start = (Elf_Addr) (si->base + phdr->p_vaddr); + si->gnu_relro_len = (unsigned) phdr->p_memsz; + } + } +@@ -1821,7 +1822,7 @@ static int link_image(soinfo *si, unsign + si->strtab = (const char *) (si->base + *d); + break; + case DT_SYMTAB: +- si->symtab = (Elf32_Sym *) (si->base + *d); ++ si->symtab = (Elf_Sym *) (si->base + *d); + break; + case DT_PLTREL: + if(*d != DT_REL) { +@@ -1830,13 +1831,13 @@ static int link_image(soinfo *si, unsign + } + break; + case DT_JMPREL: +- si->plt_rel = (Elf32_Rel*) (si->base + *d); ++ si->plt_rel = (Elf_Rel*) (si->base + *d); + break; + case DT_PLTRELSZ: + si->plt_rel_count = *d / 8; + break; + case DT_REL: +- si->rel = (Elf32_Rel*) (si->base + *d); ++ si->rel = (Elf_Rel*) (si->base + *d); + break; + case DT_RELSZ: + si->rel_count = *d / 8; +@@ -1868,7 +1869,7 @@ static int link_image(soinfo *si, unsign + pid, si->name, si->init_array); + break; + case DT_INIT_ARRAYSZ: +- si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); ++ si->init_array_count = ((unsigned)*d) / sizeof(Elf_Addr); + break; + case DT_FINI_ARRAY: + si->fini_array = (unsigned *)(si->base + *d); +@@ -1876,7 +1877,7 @@ static int link_image(soinfo *si, unsign + pid, si->name, si->fini_array); + break; + case DT_FINI_ARRAYSZ: +- si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); ++ si->fini_array_count = ((unsigned)*d) / sizeof(Elf_Addr); + break; + case DT_PREINIT_ARRAY: + si->preinit_array = (unsigned *)(si->base + *d); +@@ -1884,7 +1885,7 @@ static int link_image(soinfo *si, unsign + pid, si->name, si->preinit_array); + break; + case DT_PREINIT_ARRAYSZ: +- si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); ++ si->preinit_array_count = ((unsigned)*d) / sizeof(Elf_Addr); + break; + case DT_TEXTREL: + /* TODO: make use of this. */ +@@ -1986,7 +1987,7 @@ static int link_image(soinfo *si, unsign + #endif + + if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) { +- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); ++ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); + unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; + if (mprotect((void *) start, len, PROT_READ) < 0) { + DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n", +@@ -2169,7 +2170,7 @@ sanitize: + while(vecs[0] != 0){ + switch(vecs[0]){ + case AT_PHDR: +- si->phdr = (Elf32_Phdr*) vecs[1]; ++ si->phdr = (Elf_Phdr*) vecs[1]; + break; + case AT_PHNUM: + si->phnum = (int) vecs[1]; +@@ -2189,7 +2190,7 @@ sanitize: + si->base = 0; + for ( nn = 0; nn < si->phnum; nn++ ) { + if (si->phdr[nn].p_type == PT_PHDR) { +- si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_vaddr; ++ si->base = (Elf_Addr) si->phdr - si->phdr[nn].p_vaddr; + break; + } + } +@@ -2302,9 +2303,9 @@ static unsigned find_linker_base(unsigne + */ + unsigned __linker_init(unsigned **elfdata) { + unsigned linker_addr = find_linker_base(elfdata); +- Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_addr; +- Elf32_Phdr *phdr = +- (Elf32_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); ++ Elf_Ehdr *elf_hdr = (Elf_Ehdr *) linker_addr; ++ Elf_Phdr *phdr = ++ (Elf_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); + + soinfo linker_so; + memset(&linker_so, 0, sizeof(soinfo)); +@@ -2333,3 +2334,8 @@ unsigned __linker_init(unsigned **elfdat + // the main part of the linker now. + return __linker_init_post_relocation(elfdata); + } ++ ++void android_linker_init(int sdk_version, void *(get_hooked_symbol)(const char*, const char*)) { ++ (void) sdk_version; ++ _get_hooked_symbol = get_hooked_symbol; ++} +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.h +@@ -38,6 +38,26 @@ + #define PAGE_SIZE 4096 + #define PAGE_MASK 4095 + ++#if defined(__x86_64__) ++typedef Elf64_Ehdr Elf_Ehdr; ++typedef Elf64_Shdr Elf_Shdr; ++typedef Elf64_Sym Elf_Sym; ++typedef Elf64_Addr Elf_Addr; ++typedef Elf64_Phdr Elf_Phdr; ++typedef Elf64_Half Elf_Half; ++typedef Elf64_Rel Elf_Rel; ++typedef Elf64_Rela Elf_Rela; ++#else ++typedef Elf32_Ehdr Elf_Ehdr; ++typedef Elf32_Shdr Elf_Shdr; ++typedef Elf32_Sym Elf_Sym; ++typedef Elf32_Addr Elf_Addr; ++typedef Elf32_Phdr Elf_Phdr; ++typedef Elf32_Half Elf_Half; ++typedef Elf32_Rel Elf_Rel; ++typedef Elf32_Rela Elf_Rela; ++#endif ++ + void debugger_init(); + const char *addr_to_name(unsigned addr); + +@@ -55,10 +75,10 @@ struct link_map + /* needed for dl_iterate_phdr to be passed to the callbacks provided */ + struct dl_phdr_info + { +- Elf32_Addr dlpi_addr; ++ Elf_Addr dlpi_addr; + const char *dlpi_name; +- const Elf32_Phdr *dlpi_phdr; +- Elf32_Half dlpi_phnum; ++ const Elf_Phdr *dlpi_phdr; ++ Elf_Half dlpi_phnum; + }; + + +@@ -90,7 +110,7 @@ typedef struct soinfo soinfo; + struct soinfo + { + const char name[SOINFO_NAME_LEN]; +- Elf32_Phdr *phdr; ++ Elf_Phdr *phdr; + int phnum; + unsigned entry; + unsigned base; +@@ -107,7 +127,7 @@ struct soinfo + unsigned flags; + + const char *strtab; +- Elf32_Sym *symtab; ++ Elf_Sym *symtab; + + unsigned nbucket; + unsigned nchain; +@@ -116,10 +136,10 @@ struct soinfo + + unsigned *plt_got; + +- Elf32_Rel *plt_rel; ++ Elf_Rel *plt_rel; + unsigned plt_rel_count; + +- Elf32_Rel *rel; ++ Elf_Rel *rel; + unsigned rel_count; + + unsigned *preinit_array; +@@ -144,7 +164,7 @@ struct soinfo + + int constructors_called; + +- Elf32_Addr gnu_relro_start; ++ Elf_Addr gnu_relro_start; + unsigned gnu_relro_len; + + }; +@@ -202,18 +222,17 @@ extern soinfo libdl_info; + + soinfo *find_library(const char *name); + unsigned unload_library(soinfo *si); +-Elf32_Sym *lookup_in_library(soinfo *si, const char *name); +-Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); ++Elf_Sym *lookup_in_library(soinfo *si, const char *name); ++Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start); + soinfo *find_containing_library(const void *addr); +-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); ++Elf_Sym *find_containing_symbol(const void *addr, soinfo *si); + const char *linker_get_error(void); + void call_constructors_recursive(soinfo *si); + ++int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); + #ifdef ANDROID_ARM_LINKER + typedef long unsigned int *_Unwind_Ptr; + _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); +-#elif defined(ANDROID_X86_LINKER) +-int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); + #endif + + #endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker_format.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker_format.c +@@ -268,7 +268,7 @@ static int log_vprint(int prio, const ch + result = vformat_buffer(buf, sizeof buf, fmt, args); + + if (log_fd < 0) { +- log_fd = open("/dev/log/main", O_WRONLY); ++ log_fd = open("/dev/alog/main", O_WRONLY); + if (log_fd < 0) { + log_fd = fileno(stdout); // kernel doesn't have android log + return result; +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/Makefile.am +@@ -0,0 +1,50 @@ ++bionic = $(top_srcdir)/common/mm/bionic ++bionic_libc = $(bionic)/libc ++ ++modlibexecdir = $(libdir)/libhybris/linker ++modlibexec_LTLIBRARIES = mm.la ++ ++ARCH_FLAGS = ++ ++AM_CFLAGS = \ ++ -std=gnu99 ++ ++AM_CPPFLAGS = \ ++ -std=gnu++11 \ ++ -Wold-style-cast \ ++ -fno-stack-protector \ ++ -Wstrict-overflow=5 ++ ++mm_la_SOURCES = \ ++ hybris_compat.cpp \ ++ dlfcn.cpp \ ++ linker_allocator.cpp \ ++ linker_block_allocator.cpp \ ++ linker.cpp \ ++ linker_memory.cpp \ ++ linker_phdr.cpp \ ++ linker_sdk_versions.cpp \ ++ rt.cpp \ ++ ../strlcpy.c \ ++ ../strlcat.c ++mm_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@\"" \ ++ $(ARCH_FLAGS) \ ++ $(ANDROID_HEADERS_CFLAGS) ++mm_la_LDFLAGS = \ ++ -lsupc++ \ ++ -module \ ++ -avoid-version ++ ++if WANT_DEBUG ++mm_la_CPPFLAGS += \ ++ -DTRACE_DEBUG=1 ++else ++mm_la_CPPFLAGS += \ ++ -DTRACE_DEBUG=1 ++endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/NOTICE +@@ -0,0 +1,204 @@ ++Copyright (C) 2007 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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2010 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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ ++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. ++ ++------------------------------------------------------------------- ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/bionic/pthread_internal.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. ++ */ ++#ifndef _PTHREAD_INTERNAL_H_ ++#define _PTHREAD_INTERNAL_H_ ++ ++#include ++#include ++ ++#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 ++ ++struct pthread_key_data_t { ++ uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below. ++ void* data; ++}; ++ ++enum ThreadJoinState { ++ THREAD_NOT_JOINED, ++ THREAD_EXITED_NOT_JOINED, ++ THREAD_JOINED, ++ THREAD_DETACHED ++}; ++ ++struct pthread_internal_t { ++ struct pthread_internal_t* next; ++ struct 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; ++ ++ ThreadJoinState join_state; ++ ++ //__pthread_cleanup_t* cleanup_stack; ++ ++ void* (*start_routine)(void*); ++ void* start_routine_arg; ++ void* return_value; ++ ++ void* alternate_signal_stack; ++ ++ pthread_mutex_t startup_handshake_mutex; ++ ++ size_t mmap_size; ++ ++ void* tls[BIONIC_TLS_SLOTS]; ++ ++ pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT]; ++ ++ /* ++ * 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). ++ */ ++#define __BIONIC_DLERROR_BUFFER_SIZE 512 ++ char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE]; ++}; ++ ++ int __init_thread(pthread_internal_t* thread); ++ void __init_tls(pthread_internal_t* thread); ++ void __init_alternate_signal_stack(pthread_internal_t*); ++ ++ pthread_t __pthread_internal_add(pthread_internal_t* thread); ++ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id); ++ void __pthread_internal_remove(pthread_internal_t* thread); ++ void __pthread_internal_remove_and_free(pthread_internal_t* thread); ++ ++// Make __get_thread() inlined for performance reason. See http://b/19825434. ++static inline pthread_internal_t* __get_thread() { ++ return reinterpret_cast(__get_tls()[TLS_SLOT_THREAD_ID]); ++} ++ ++ void pthread_key_clean_all(void); ++ ++/* ++ * 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) - SIGSTKSZ) ++ ++/* Leave room for a guard page in the internally created signal stacks. */ ++#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE) ++ ++/* Needed by fork. */ ++ extern void __bionic_atfork_run_prepare(); ++ extern void __bionic_atfork_run_child(); ++ extern void __bionic_atfork_run_parent(); ++ ++#endif /* _PTHREAD_INTERNAL_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/include/android/api-level.h +@@ -0,0 +1,38 @@ ++/* ++ * 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 ANDROID_API_LEVEL_H ++#define ANDROID_API_LEVEL_H ++ ++/* ++ * Magic version number for a current development build, which has ++ * not yet turned into an official release. ++ */ ++#define __ANDROID_API__ 10000 ++ ++#endif /* ANDROID_API_LEVEL_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/include/android/dlext.h +@@ -0,0 +1,107 @@ ++/* ++ * 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 ++#include ++#include ++#include /* for off64_t */ ++ ++__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, the load ++ * will fail. ++ */ ++ ANDROID_DLEXT_RESERVED_ADDRESS = 0x1, ++ ++ /* As 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. ++ */ ++ 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. ++ */ ++ ANDROID_DLEXT_USE_RELRO = 0x8, ++ ++ /* Instruct dlopen to use library_fd instead of opening 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 flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set. ++ */ ++ ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET = 0x20, ++ ++ /* When set, do not check if the library has already been loaded by file stat(2)s. ++ * ++ * 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 DT_NEEDED list, the first one will be used to resolve any ++ * dependencies. ++ */ ++ ANDROID_DLEXT_FORCE_LOAD = 0x40, ++ ++ /* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero, ++ * the dynamic linker will load it at that address. ++ * ++ * This flag is for ART internal use only. ++ */ ++ ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80, ++ ++ /* 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_FORCE_FIXED_VADDR, ++}; ++ ++typedef struct { ++ uint64_t flags; ++ void* reserved_addr; ++ size_t reserved_size; ++ int relro_fd; ++ int library_fd; ++ off64_t library_fd_offset; ++} android_dlextinfo; ++ ++extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo); ++ ++__END_DECLS ++ ++#endif /* __ANDROID_DLEXT_H__ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/include/link.h +@@ -0,0 +1,80 @@ ++/* ++ * 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 ++#include ++ ++__BEGIN_DECLS ++ ++#if __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; ++}; ++ ++int dl_iterate_phdr(int (*)(struct dl_phdr_info*, size_t, void*), void*); ++ ++#ifdef __arm__ ++typedef long unsigned int* _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 /* _LINK_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ErrnoRestorer.h +@@ -0,0 +1,43 @@ ++/* ++ * 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 ERRNO_RESTORER_H ++#define ERRNO_RESTORER_H ++ ++#include ++ ++#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_; ++ ++ DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer); ++}; ++ ++#endif // ERRNO_RESTORER_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/KernelArgumentBlock.h +@@ -0,0 +1,81 @@ ++/* ++ * 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 KERNEL_ARGUMENT_BLOCK_H ++#define KERNEL_ARGUMENT_BLOCK_H ++ ++#include ++#include ++#include ++#include ++ ++#include "private/bionic_macros.h" ++ ++struct abort_msg_t; ++ ++// 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: ++ KernelArgumentBlock(void* raw_args) { ++ uintptr_t* args = reinterpret_cast(raw_args); ++ argc = static_cast(*args); ++ argv = reinterpret_cast(args + 1); ++ envp = argv + argc + 1; ++ ++ // Skip over all environment variable definitions to find aux vector. ++ // The end of the environment block is marked by two NULL pointers. ++ char** p = envp; ++ while (*p != NULL) { ++ ++p; ++ } ++ ++p; // Skip second NULL; ++ ++ auxv = reinterpret_cast(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. This function also lets you distinguish ++ // between the inability to find the given type and its value just happening to be 0. ++ unsigned long getauxval(unsigned long type, bool* found_match = NULL) { ++ for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) { ++ if (v->a_type == type) { ++ if (found_match != NULL) { ++ *found_match = true; ++ } ++ return v->a_un.a_val; ++ } ++ } ++ if (found_match != NULL) { ++ *found_match = false; ++ } ++ return 0; ++ } ++ ++ int argc; ++ char** argv; ++ char** envp; ++ ElfW(auxv_t)* auxv; ++ ++ abort_msg_t** abort_message_ptr; ++ ++ private: ++ DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock); ++}; ++ ++#endif // KERNEL_ARGUMENT_BLOCK_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/NetdClientDispatch.h +@@ -0,0 +1,36 @@ ++/* ++ * 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 ++#include ++ ++__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); ++}; ++ ++extern struct NetdClientDispatch __netdClientDispatch; ++ ++__END_DECLS ++ ++#endif // PRIVATE_NETD_CLIENT_DISPATCH_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ScopeGuard.h +@@ -0,0 +1,53 @@ ++/* ++ * 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 _SCOPE_GUARD_H ++#define _SCOPE_GUARD_H ++ ++#include "private/bionic_macros.h" ++ ++// TODO: include explicit std::move when it becomes available ++template ++class ScopeGuard { ++ public: ++ ScopeGuard(F f) : f_(f), active_(true) {} ++ ++ ScopeGuard(ScopeGuard&& that) : f_(that.f_), active_(that.active_) { ++ that.active_ = false; ++ } ++ ++ ~ScopeGuard() { ++ if (active_) { ++ f_(); ++ } ++ } ++ ++ void disable() { ++ active_ = false; ++ } ++ private: ++ F f_; ++ bool active_; ++ ++ DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeGuard); ++}; ++ ++template ++ScopeGuard make_scope_guard(T f) { ++ return ScopeGuard(f); ++} ++ ++#endif // _SCOPE_GUARD_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ScopedPthreadMutexLocker.h +@@ -0,0 +1,40 @@ ++/* ++ * 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. ++ */ ++ ++#ifndef SCOPED_PTHREAD_MUTEX_LOCKER_H ++#define SCOPED_PTHREAD_MUTEX_LOCKER_H ++ ++#include ++ ++#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_; ++ ++ DISALLOW_COPY_AND_ASSIGN(ScopedPthreadMutexLocker); ++}; ++ ++#endif // SCOPED_PTHREAD_MUTEX_LOCKER_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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. ++ */ ++ ++#ifndef SCOPED_READDIR_H ++#define SCOPED_READDIR_H ++ ++#include ++ ++#include "private/bionic_macros.h" ++ ++class ScopedReaddir { ++ public: ++ ScopedReaddir(const char* path) { ++ dir_ = opendir(path); ++ } ++ ++ ~ScopedReaddir() { ++ if (dir_ != NULL) { ++ closedir(dir_); ++ } ++ } ++ ++ bool IsBad() { ++ return dir_ == NULL; ++ } ++ ++ dirent* ReadEntry() { ++ return readdir(dir_); ++ } ++ ++ private: ++ DIR* dir_; ++ ++ DISALLOW_COPY_AND_ASSIGN(ScopedReaddir); ++}; ++ ++#endif // SCOPED_READDIR_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ThreadLocalBuffer.h +@@ -0,0 +1,61 @@ ++/* ++ * 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 _BIONIC_THREAD_LOCAL_BUFFER_H_included ++#define _BIONIC_THREAD_LOCAL_BUFFER_H_included ++ ++#include ++#include ++ ++// TODO: use __thread instead? ++ ++template ++class ThreadLocalBuffer { ++ public: ++ ThreadLocalBuffer() { ++ // We used to use pthread_once to initialize the keys, but life is more predictable ++ // if we allocate them all up front when the C library starts up, via __constructor__. ++ pthread_key_create(&key_, free); ++ } ++ ++ T* get() { ++ T* result = reinterpret_cast(pthread_getspecific(key_)); ++ if (result == nullptr) { ++ result = reinterpret_cast(calloc(1, Size)); ++ pthread_setspecific(key_, result); ++ } ++ return result; ++ } ++ ++ size_t size() { return Size; } ++ ++ private: ++ pthread_key_t key_; ++}; ++ ++#endif // _BIONIC_THREAD_LOCAL_BUFFER_H_included +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/UniquePtr.h +@@ -0,0 +1,140 @@ ++/* ++ * 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. ++ */ ++ ++#ifndef UNIQUE_PTR_H_included ++#define UNIQUE_PTR_H_included ++ ++// Default deleter for pointer types. ++template ++struct DefaultDelete { ++ enum { type_must_be_complete = sizeof(T) }; ++ DefaultDelete() {} ++ void operator()(T* p) const { ++ delete p; ++ } ++}; ++ ++// Default deleter for array types. ++template ++struct DefaultDelete { ++ enum { type_must_be_complete = sizeof(T) }; ++ void operator()(T* p) const { ++ delete[] p; ++ } ++}; ++ ++// A smart pointer that deletes the given pointer on destruction. ++// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr ++// and boost::scoped_array). ++// Named to be in keeping with Android style but also to avoid ++// collision with any other implementation, until we can switch over ++// to unique_ptr. ++// Use thus: ++// UniquePtr c(new C); ++template > ++class UniquePtr { ++public: ++ // Construct a new UniquePtr, taking ownership of the given raw pointer. ++ explicit UniquePtr(T* ptr = nullptr) : mPtr(ptr) { } ++ ++ UniquePtr(UniquePtr&& that) { ++ mPtr = that.mPtr; ++ that.mPtr = nullptr; ++ } ++ ++ ~UniquePtr() { ++ reset(); ++ } ++ ++ // Accessors. ++ T& operator*() const { return *mPtr; } ++ T* operator->() const { return mPtr; } ++ T* get() const { return mPtr; } ++ ++ // Returns the raw pointer and hands over ownership to the caller. ++ // The pointer will not be deleted by UniquePtr. ++ T* release() __attribute__((warn_unused_result)) { ++ T* result = mPtr; ++ mPtr = nullptr; ++ return result; ++ } ++ ++ // Takes ownership of the given raw pointer. ++ // If this smart pointer previously owned a different raw pointer, that ++ // raw pointer will be freed. ++ void reset(T* ptr = nullptr) { ++ if (ptr != mPtr) { ++ D()(mPtr); ++ mPtr = ptr; ++ } ++ } ++ ++private: ++ // The raw pointer. ++ T* mPtr; ++ ++ // Comparing unique pointers is probably a mistake, since they're unique. ++ template bool operator==(const UniquePtr& p) const = delete; ++ template bool operator!=(const UniquePtr& p) const = delete; ++ ++ // Disallow copy and assignment. ++ UniquePtr(const UniquePtr&) = delete; ++ void operator=(const UniquePtr&) = delete; ++}; ++ ++// Partial specialization for array types. Like std::unique_ptr, this removes ++// operator* and operator-> but adds operator[]. ++template ++class UniquePtr { ++public: ++ explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) { ++ } ++ UniquePtr(UniquePtr&& that) { ++ mPtr = that.mPtr; ++ that.mPtr = nullptr; ++ } ++ ++ ~UniquePtr() { ++ reset(); ++ } ++ ++ T& operator[](size_t i) const { ++ return mPtr[i]; ++ } ++ T* get() const { return mPtr; } ++ ++ T* release() __attribute__((warn_unused_result)) { ++ T* result = mPtr; ++ mPtr = NULL; ++ return result; ++ } ++ ++ void reset(T* ptr = NULL) { ++ if (ptr != mPtr) { ++ D()(mPtr); ++ mPtr = ptr; ++ } ++ } ++ ++private: ++ T* mPtr; ++ ++ // Disallow copy and assignment. ++ UniquePtr(const UniquePtr&) = delete; ++ void operator=(const UniquePtr&) = delete; ++}; ++ ++#endif // UNIQUE_PTR_H_included +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_asm.h +@@ -0,0 +1,64 @@ ++/* ++ * 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 /* 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 ++ ++#include ++ ++#define ENTRY(f) \ ++ .text; \ ++ .globl f; \ ++ .align __bionic_asm_align; \ ++ .type f, __bionic_asm_function_type; \ ++ f: \ ++ __bionic_asm_custom_entry(f); \ ++ .cfi_startproc \ ++ ++#define END(f) \ ++ .cfi_endproc; \ ++ .size f, .-f; \ ++ __bionic_asm_custom_end(f) \ ++ ++/* Like ENTRY, but with hidden visibility. */ ++#define ENTRY_PRIVATE(f) \ ++ ENTRY(f); \ ++ .hidden f \ ++ ++#define ALIAS_SYMBOL(alias, original) \ ++ .globl alias; \ ++ .equ alias, original ++ ++#endif /* _PRIVATE_BIONIC_ASM_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_auxv.h +@@ -0,0 +1,41 @@ ++/* ++ * 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_AUXV_H_ ++#define _PRIVATE_BIONIC_AUXV_H_ ++ ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++extern ElfW(auxv_t)* __libc_auxv; ++ ++__END_DECLS ++ ++#endif /* _PRIVATE_BIONIC_AUXV_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_constants.h +@@ -0,0 +1,22 @@ ++/* ++ * 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 ++ ++#endif // _BIONIC_CONSTANTS_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_futex.h +@@ -0,0 +1,72 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++struct timespec; ++ ++static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) { ++ // 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); ++ if (__predict_false(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, NULL); ++} ++ ++static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) { ++ return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL); ++} ++ ++static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) { ++ return __futex(ftx, FUTEX_WAIT, value, timeout); ++} ++ ++static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) { ++ return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout); ++} ++ ++__END_DECLS ++ ++#endif /* _BIONIC_FUTEX_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_lock.h +@@ -0,0 +1,74 @@ ++/* ++ * 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 _BIONIC_LOCK_H ++#define _BIONIC_LOCK_H ++ ++#include ++#include "private/bionic_futex.h" ++ ++class Lock { ++ private: ++ enum LockState { ++ Unlocked = 0, ++ LockedWithoutWaiter, ++ LockedWithWaiter, ++ }; ++ _Atomic(LockState) state; ++ bool process_shared; ++ ++ public: ++ Lock(bool process_shared = false) { ++ init(process_shared); ++ } ++ ++ void init(bool process_shared) { ++ atomic_init(&state, Unlocked); ++ this->process_shared = process_shared; ++ } ++ ++ void lock() { ++ LockState old_state = Unlocked; ++ if (__predict_true(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, NULL); ++ } ++ return; ++ } ++ ++ void unlock() { ++ if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) { ++ __futex_wake_ex(&state, process_shared, 1); ++ } ++ } ++}; ++ ++#endif // _BIONIC_LOCK_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_macros.h +@@ -0,0 +1,49 @@ ++/* ++ * 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. ++ */ ++ ++#ifndef _BIONIC_MACROS_H_ ++#define _BIONIC_MACROS_H_ ++ ++// Frameworks OpenGL code currently leaks this header and allows ++// collisions with other declarations, e.g., from libnativehelper. ++// TODO: Remove once cleaned up. b/18334516 ++#if !defined(DISALLOW_COPY_AND_ASSIGN) ++// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. ++// It goes in the private: declarations in a class. ++#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ ++ TypeName(const TypeName&) = delete; \ ++ void operator=(const TypeName&) = delete ++#endif // !defined(DISALLOW_COPY_AND_ASSIGN) ++ ++// 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) ++ ++#define BIONIC_ALIGN(value, alignment) \ ++ (((value) + (alignment) - 1) & ~((alignment) - 1)) ++ ++#define BIONIC_ROUND_UP_POWER_OF_2(value) \ ++ (sizeof(value) == 8) \ ++ ? (1UL << (64 - __builtin_clzl(static_cast(value)))) \ ++ : (1UL << (32 - __builtin_clz(static_cast(value)))) ++ ++#endif // _BIONIC_MACROS_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_mbstate.h +@@ -0,0 +1,54 @@ ++/* ++ * 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 ++ ++__BEGIN_DECLS ++ ++/* ++ * These return values are specified by POSIX for multibyte conversion ++ * functions. ++ */ ++#define __MB_ERR_ILLEGAL_SEQUENCE static_cast(-1) ++#define __MB_ERR_INCOMPLETE_SEQUENCE static_cast(-2) ++ ++#define __MB_IS_ERR(rv) (rv == __MB_ERR_ILLEGAL_SEQUENCE || \ ++ rv == __MB_ERR_INCOMPLETE_SEQUENCE) ++ ++size_t mbstate_bytes_so_far(const mbstate_t* ps); ++void mbstate_set_byte(mbstate_t* ps, int i, char byte); ++uint8_t mbstate_get_byte(const mbstate_t* ps, int n); ++size_t reset_and_return_illegal(int _errno, mbstate_t* ps); ++size_t reset_and_return(int _return, mbstate_t* ps); ++ ++__END_DECLS ++ ++#endif // _BIONIC_MBSTATE_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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 ++ ++// 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 +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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 ++#include ++ ++__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 +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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 ++ ++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_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_systrace.h +@@ -0,0 +1,35 @@ ++/* ++ * 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_SYSTRACE_H ++#define BIONIC_SYSTRACE_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 ScopedTrace { ++ public: ++ explicit ScopedTrace(const char* message); ++ ~ScopedTrace(); ++ ++ private: ++ DISALLOW_COPY_AND_ASSIGN(ScopedTrace); ++}; ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_time.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2011 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_H ++#define _BIONIC_TIME_H ++ ++#include ++#include ++ ++__BEGIN_DECLS ++ ++// We can't remove this (and this file) until we fix MtpUtils.cpp. ++time_t mktime_tz(struct tm* const, char const*); ++ ++__END_DECLS ++ ++#endif /* _BIONIC_TIME_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_time_conversions.h +@@ -0,0 +1,46 @@ ++/* ++ * 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 ++#include ++ ++__BEGIN_DECLS ++ ++ bool timespec_from_timeval(timespec& ts, const timeval& tv); ++ void timespec_from_ms(timespec& ts, const int ms); ++ ++ void timeval_from_timespec(timeval& tv, const timespec& ts); ++ ++ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock); ++ ++__END_DECLS ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_tls.h +@@ -0,0 +1,120 @@ ++/* ++ * 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_BIONIC_TLS_H_ ++#define __BIONIC_PRIVATE_BIONIC_TLS_H_ ++ ++#include ++#include ++#include "bionic_macros.h" ++#include "__get_tls.h" ++ ++__BEGIN_DECLS ++ ++/** 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 the system dynamic ++ ** linker and the OpenGL sub-system (which needs to access the ++ ** pre-allocated slot directly for performance reason). ++ **/ ++ ++// Well-known TLS slots. What data goes in which slot is arbitrary unless otherwise noted. ++enum { ++ TLS_SLOT_SELF = 0, // The kernel requires this specific slot for x86. ++ TLS_SLOT_THREAD_ID, ++ TLS_SLOT_ERRNO = 5, ++ ++ // 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_OPENGL_API = 6, ++ TLS_SLOT_OPENGL = 7, ++ ++ // This slot is only used to pass information from the dynamic linker to ++ // libc.so when the C library is loaded in to memory. The C runtime init ++ // function will then clear it. Since its use is extremely temporary, ++ // we reuse an existing location that isn't needed during libc startup. ++ TLS_SLOT_BIONIC_PREINIT = TLS_SLOT_OPENGL_API, ++ ++ TLS_SLOT_STACK_GUARD = 8, // GCC requires this specific slot for x86. ++ TLS_SLOT_DLERROR, ++ ++ BIONIC_TLS_SLOTS // Must come last! ++}; ++ ++/* ++ * 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: ++ * ++ * basename libc (ThreadLocalBuffer) ++ * dirname libc (ThreadLocalBuffer) ++ * uselocale libc (can be used in constructors) ++ * getmntent_mntent libc (ThreadLocalBuffer) ++ * getmntent_strings libc (ThreadLocalBuffer) ++ * ptsname libc (ThreadLocalBuffer) ++ * ttyname libc (ThreadLocalBuffer) ++ * strerror libc (ThreadLocalBuffer) ++ * strsignal libc (ThreadLocalBuffer) ++ * passwd libc (ThreadLocalBuffer) ++ * group libc (ThreadLocalBuffer) ++ * _res_key libc (constructor in BSD code) ++ */ ++ ++#define LIBC_PTHREAD_KEY_RESERVED_COUNT 12 ++ ++#if defined(USE_JEMALLOC) ++/* 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) ++#else ++#define BIONIC_PTHREAD_KEY_RESERVED_COUNT LIBC_PTHREAD_KEY_RESERVED_COUNT ++#endif ++ ++/* ++ * 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) ++ ++__END_DECLS ++ ++#if defined(__cplusplus) ++class KernelArgumentBlock; ++extern void __libc_init_tls(KernelArgumentBlock& args); ++#endif ++ ++#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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 ++ ++// 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 +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/libc_events.h +@@ -0,0 +1,50 @@ ++/* ++ * 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 _LIBC_EVENTS_H ++#define _LIBC_EVENTS_H ++ ++ ++// This is going to be included in assembler code so only allow #define ++// values instead of defining an enum. ++ ++#define BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW 80100 ++#define BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW 80105 ++#define BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW 80110 ++#define BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW 80115 ++#define BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW 80120 ++#define BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW 80125 ++#define BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW 80130 ++#define BIONIC_EVENT_STPCPY_BUFFER_OVERFLOW 80135 ++#define BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW 80140 ++ ++#define BIONIC_EVENT_RESOLVER_OLD_RESPONSE 80300 ++#define BIONIC_EVENT_RESOLVER_WRONG_SERVER 80305 ++#define BIONIC_EVENT_RESOLVER_WRONG_QUERY 80310 ++ ++#endif // _LIBC_EVENTS_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/libc_logging.h +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2010 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 _LIBC_LOGGING_H ++#define _LIBC_LOGGING_H ++ ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++#include "libc_events.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 */ ++}; ++ ++enum { ++ LOG_ID_MIN = 0, ++ ++ LOG_ID_MAIN = 0, ++ LOG_ID_RADIO = 1, ++ LOG_ID_EVENTS = 2, ++ LOG_ID_SYSTEM = 3, ++ LOG_ID_CRASH = 4, ++ ++ LOG_ID_MAX ++}; ++ ++struct abort_msg_t { ++ size_t size; ++ char msg[0]; ++}; ++ ++// ++// Formats a message to the log (priority 'fatal'), then aborts. ++// ++ ++ void __libc_fatal(const char* format, ...); ++ ++// ++// Formats a message to the log (priority 'fatal'), but doesn't abort. ++// Used by the malloc implementation to ensure that debuggerd dumps memory ++// around the bad address. ++// ++ ++ void __libc_fatal_no_abort(const char* format, ...); ++ ++// ++// Formatting routines for the C library's internal debugging. ++// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio. ++// ++ ++ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...); ++ ++ int __libc_format_fd(int fd, const char* format, ...); ++ ++ int __libc_format_log(int priority, const char* tag, const char* format, ...); ++ ++ int __libc_format_log_va_list(int priority, const char* tag, const char* format, ++ va_list ap); ++ ++// ++// Event logging. ++// ++ ++ void __libc_android_log_event_int(int32_t tag, int value); ++ void __libc_android_log_event_uid(int32_t tag); ++ ++ void __fortify_chk_fail(const char* msg, uint32_t event_tag); ++ ++__END_DECLS ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/thread_private.h +@@ -0,0 +1,55 @@ ++/* $OpenBSD: thread_private.h,v 1.18 2006/02/22 07:16:31 otto Exp $ */ ++ ++/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman */ ++ ++#ifndef _THREAD_PRIVATE_H_ ++#define _THREAD_PRIVATE_H_ ++ ++#include ++ ++__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. ++ */ ++ ++/* ++ * helper macro to make unique names in the thread namespace ++ */ ++#define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name) ++ ++struct __thread_private_tag_t { ++ pthread_mutex_t _private_lock; ++ pthread_key_t _private_key; ++}; ++ ++#define _THREAD_PRIVATE_MUTEX(name) \ ++ static struct __thread_private_tag_t __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 } ++#define _THREAD_PRIVATE_MUTEX_LOCK(name) \ ++ pthread_mutex_lock( &__THREAD_NAME(name)._private_lock ) ++#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ ++ pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock ) ++ ++/* 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) ++ ++ void _thread_atexit_lock(void); ++ void _thread_atexit_unlock(void); ++ ++#define _ATEXIT_LOCK() _thread_atexit_lock() ++#define _ATEXIT_UNLOCK() _thread_atexit_unlock() ++ ++ void _thread_arc4_lock(void); ++ 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)) ++ ++__END_DECLS ++ ++#endif /* _THREAD_PRIVATE_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/dlfcn.cpp +@@ -0,0 +1,298 @@ ++/* ++ * Copyright (C) 2007 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. ++ */ ++ ++#include "linker.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "private/bionic_tls.h" ++#include "private/ScopedPthreadMutexLocker.h" ++#include "private/ThreadLocalBuffer.h" ++ ++#include "hybris_compat.h" ++ ++/* This file hijacks the symbols stubbed out in libdl.so. */ ++ ++static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; ++ ++static char dl_err_buf[1024]; ++static const char *dl_err_str; ++ ++static const char* __bionic_set_dlerror(char* new_value) { ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ char** dlerror_slot = &reinterpret_cast(__get_tls())[TLS_SLOT_DLERROR]; ++ ++ const char* old_value = *dlerror_slot; ++ *dlerror_slot = new_value; ++ return old_value; ++#else ++ char *dlerror_slot = dl_err_buf; ++ const char *old_value = dlerror_slot; ++ dlerror_slot = 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 = dl_err_buf; ++#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); ++} ++ ++extern "C" const char* android_dlerror() { ++ const char* old_value = __bionic_set_dlerror(nullptr); ++ return old_value; ++} ++ ++void 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 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) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ soinfo* result = do_dlopen(filename, flags, extinfo); ++ if (result == nullptr) { ++ __bionic_format_dlerror("dlopen failed", linker_get_error_buffer()); ++ return nullptr; ++ } ++ return result; ++} ++ ++extern "C" void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) { ++ return dlopen_ext(filename, flags, extinfo); ++} ++ ++extern "C" void* android_dlopen(const char* filename, int flags) { ++ return dlopen_ext(filename, flags, nullptr); ++} ++ ++extern "C" void* android_dlsym(void* handle, const char* symbol) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ ++#if !defined(__LP64__) ++ if (handle == nullptr) { ++ __bionic_format_dlerror("dlsym library handle is null", nullptr); ++ return nullptr; ++ } ++#endif ++ ++ if (symbol == nullptr) { ++ __bionic_format_dlerror("dlsym symbol name is null", nullptr); ++ return nullptr; ++ } ++ ++ soinfo* found = nullptr; ++ const ElfW(Sym)* sym = nullptr; ++ void* caller_addr = __builtin_return_address(0); ++ soinfo* caller = find_containing_library(caller_addr); ++ ++ if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) { ++ sym = dlsym_linear_lookup(symbol, &found, caller, handle); ++ } else { ++ sym = dlsym_handle_lookup(reinterpret_cast(handle), &found, symbol); ++ } ++ ++ if (sym != nullptr) { ++ unsigned bind = ELF_ST_BIND(sym->st_info); ++ ++ if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) { ++ return reinterpret_cast(found->resolve_symbol_address(sym)); ++ } ++ ++ __bionic_format_dlerror("symbol found but not global", symbol); ++ return nullptr; ++ } else { ++ __bionic_format_dlerror("undefined symbol", symbol); ++ return nullptr; ++ } ++} ++ ++extern "C" int android_dladdr(const void* addr, Dl_info* info) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ ++ // 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(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(si->resolve_symbol_address(sym)); ++ } ++ ++ return 1; ++} ++ ++extern "C" int android_dlclose(void* handle) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ do_dlclose(reinterpret_cast(handle)); ++ // dlclose has no defined errors. ++ return 0; ++} ++ ++int 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); ++} ++ ++void android_set_application_target_sdk_version(uint32_t target) { ++ // lock to avoid modification in the middle of dlopen. ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ set_application_target_sdk_version(target); ++} ++ ++uint32_t android_get_application_target_sdk_version() { ++ return get_application_target_sdk_version(); ++} ++ ++// name_offset: starting index of the name in libdl_info.strtab ++#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \ ++ { name_offset, \ ++ reinterpret_cast(value), \ ++ /* st_size */ 0, \ ++ (shndx == 0) ? 0 : (STB_GLOBAL << 4), \ ++ /* st_other */ 0, \ ++ shndx, \ ++ } ++ ++#define ELF64_SYM_INITIALIZER(name_offset, value, shndx) \ ++ { name_offset, \ ++ (shndx == 0) ? 0 : (STB_GLOBAL << 4), \ ++ /* st_other */ 0, \ ++ shndx, \ ++ reinterpret_cast(value), \ ++ /* st_size */ 0, \ ++ } ++ ++#if defined(__arm__) ++_Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); ++#endif ++ ++static const char ANDROID_LIBDL_STRTAB[] = ++ // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 99999 ++ // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 56789 ++ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_it" ++ // 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999 ++ // 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789 ++ "erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar" ++ // 0000000000111111 ++ // 0123456789012345 ++ "get_sdk_version\0" ++#if defined(__arm__) ++ // 216 ++ "dl_unwind_find_exidx\0" ++#endif ++ ; ++ ++static ElfW(Sym) g_libdl_symtab[] = { ++ // Total length of libdl_info.strtab, including trailing 0. ++ // This is actually the STH_UNDEF entry. Technically, it's ++ // supposed to have st_name == 0, but instead, it points to an index ++ // in the strtab with a \0 to make iterating through the symtab easier. ++ ELFW(SYM_INITIALIZER)(sizeof(ANDROID_LIBDL_STRTAB) - 1, nullptr, 0), ++ ELFW(SYM_INITIALIZER)( 0, &android_dlopen, 1), ++ ELFW(SYM_INITIALIZER)( 7, &android_dlclose, 1), ++ ELFW(SYM_INITIALIZER)( 15, &android_dlsym, 1), ++ ELFW(SYM_INITIALIZER)( 21, &android_dlerror, 1), ++ ELFW(SYM_INITIALIZER)( 29, &android_dladdr, 1), ++ ELFW(SYM_INITIALIZER)( 36, &android_update_LD_LIBRARY_PATH, 1), ++ ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1), ++ ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1), ++ ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1), ++ ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1), ++ ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1), ++#if defined(__arm__) ++ ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1), ++#endif ++}; ++ ++// Fake out a hash table with a single bucket. ++// ++// A search of the hash table will look through g_libdl_symtab starting with index 1, then ++// use g_libdl_chains to find the next index to look at. g_libdl_chains should be set up to ++// walk through every element in g_libdl_symtab, and then end with 0 (sentinel value). ++// ++// That is, g_libdl_chains should look like { 0, 2, 3, ... N, 0 } where N is the number ++// of actual symbols, or nelems(g_libdl_symtab)-1 (since the first element of g_libdl_symtab is not ++// a real symbol). (See soinfo_elf_lookup().) ++// ++// Note that adding any new symbols here requires stubbing them out in libdl. ++static unsigned g_libdl_buckets[1] = { 1 }; ++#if defined(__arm__) ++static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 }; ++#else ++static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 }; ++#endif ++ ++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() { ++ if (__libdl_info == nullptr) { ++ __libdl_info = new (__libdl_info_buf) soinfo("libdl.so", nullptr, 0, RTLD_GLOBAL); ++ __libdl_info->flags_ |= FLAG_LINKED; ++ __libdl_info->strtab_ = ANDROID_LIBDL_STRTAB; ++ __libdl_info->symtab_ = g_libdl_symtab; ++ __libdl_info->nbucket_ = sizeof(g_libdl_buckets)/sizeof(unsigned); ++ __libdl_info->nchain_ = sizeof(g_libdl_chains)/sizeof(unsigned); ++ __libdl_info->bucket_ = g_libdl_buckets; ++ __libdl_info->chain_ = g_libdl_chains; ++ __libdl_info->ref_count_ = 1; ++ __libdl_info->strtab_size_ = sizeof(ANDROID_LIBDL_STRTAB); ++ __libdl_info->local_group_root_ = __libdl_info; ++ __libdl_info->soname_ = "libdl.so"; ++ __libdl_info->target_sdk_version_ = __ANDROID_API__; ++#if DISABLED_FOR_HYBRIS_SUPPORT ++#if defined(__arm__) ++ strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_)); ++#endif ++#endif ++ } ++ ++ return __libdl_info; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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" +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/hybris_compat.h +@@ -0,0 +1,58 @@ ++/* ++ * 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 ++#include ++ ++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 ++ * ++ * 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) ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linked_list.h +@@ -0,0 +1,180 @@ ++/* ++ * 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 __LINKED_LIST_H ++#define __LINKED_LIST_H ++ ++#include "private/bionic_macros.h" ++ ++template ++struct LinkedListEntry { ++ LinkedListEntry* next; ++ T* element; ++}; ++ ++/* ++ * Represents linked list of objects of type T ++ */ ++template ++class LinkedList { ++ public: ++ LinkedList() : head_(nullptr), tail_(nullptr) {} ++ ~LinkedList() { ++ clear(); ++ } ++ ++ LinkedList(LinkedList&& that) { ++ this->head_ = that.head_; ++ this->tail_ = that.tail_; ++ that.head_ = that.tail_ = nullptr; ++ } ++ ++ void push_front(T* const element) { ++ LinkedListEntry* 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* 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* 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* p = head_; ++ head_ = head_->next; ++ Allocator::free(p); ++ } ++ ++ tail_ = nullptr; ++ } ++ ++ template ++ void for_each(F action) const { ++ visit([&] (T* si) { ++ action(si); ++ return true; ++ }); ++ } ++ ++ template ++ bool visit(F action) const { ++ for (LinkedListEntry* e = head_; e != nullptr; e = e->next) { ++ if (!action(e->element)) { ++ return false; ++ } ++ } ++ return true; ++ } ++ ++ template ++ void remove_if(F predicate) { ++ for (LinkedListEntry* e = head_, *p = nullptr; e != nullptr;) { ++ if (predicate(e->element)) { ++ LinkedListEntry* next = e->next; ++ if (p == nullptr) { ++ head_ = next; ++ } else { ++ p->next = next; ++ } ++ Allocator::free(e); ++ e = next; ++ } else { ++ p = e; ++ e = e->next; ++ } ++ } ++ } ++ ++ template ++ T* find_if(F predicate) const { ++ for (LinkedListEntry* e = head_; e != nullptr; e = e->next) { ++ if (predicate(e->element)) { ++ return e->element; ++ } ++ } ++ ++ return nullptr; ++ } ++ ++ size_t copy_to_array(T* array[], size_t array_length) const { ++ size_t sz = 0; ++ for (LinkedListEntry* e = head_; sz < array_length && e != nullptr; e = e->next) { ++ array[sz++] = e->element; ++ } ++ ++ return sz; ++ } ++ ++ bool contains(const T* el) const { ++ for (LinkedListEntry* e = head_; e != nullptr; e = e->next) { ++ if (e->element == el) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ static LinkedList make_list(T* const element) { ++ LinkedList one_element_list; ++ one_element_list.push_back(element); ++ return one_element_list; ++ } ++ ++ private: ++ LinkedListEntry* head_; ++ LinkedListEntry* tail_; ++ DISALLOW_COPY_AND_ASSIGN(LinkedList); ++}; ++ ++#endif // __LINKED_LIST_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker.cpp +@@ -0,0 +1,3391 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++// Private C library headers. ++#include "private/bionic_tls.h" ++#include "private/KernelArgumentBlock.h" ++#include "private/ScopedPthreadMutexLocker.h" ++#include "private/ScopeGuard.h" ++#include "private/UniquePtr.h" ++ ++#include "linker.h" ++#include "linker_block_allocator.h" ++#include "linker_debug.h" ++#include "linker_sleb128.h" ++#include "linker_phdr.h" ++#include "linker_relocs.h" ++#include "linker_reloc_iterators.h" ++ ++#include "hybris_compat.h" ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++extern void __libc_init_AT_SECURE(KernelArgumentBlock&); ++#endif ++ ++// Override macros to use C++ style casts. ++#undef ELF_ST_TYPE ++#define ELF_ST_TYPE(x) (static_cast(x) & 0xf) ++ ++static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf); ++ ++static LinkerTypeAllocator g_soinfo_allocator; ++static LinkerTypeAllocator> g_soinfo_links_allocator; ++ ++static soinfo* solist = get_libdl_info(); ++static soinfo* sonext = get_libdl_info(); ++static soinfo* somain; // main process, always the one after libdl_info ++ ++static const char* const kDefaultLdPaths[] = { ++#if defined(__LP64__) ++ "/vendor/lib64", ++ "/system/lib64", ++#else ++ "/vendor/lib", ++ "/system/lib", ++#endif ++ nullptr ++}; ++ ++static const ElfW(Versym) kVersymNotNeeded = 0; ++static const ElfW(Versym) kVersymGlobal = 1; ++ ++static std::vector g_ld_library_paths; ++static std::vector g_ld_preload_names; ++ ++static std::vector g_ld_preloads; ++ ++int g_ld_debug_verbosity = 0; ++ ++abort_msg_t* g_abort_message = nullptr; // For debuggerd. ++ ++#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 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); ++} ++ ++// 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(); ++ ++static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER; ++static r_debug _r_debug = ++ {1, nullptr, reinterpret_cast(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0}; ++ ++static link_map* r_debug_tail = 0; ++ ++static void* (*_get_hooked_symbol)(const char *sym, const char *requester); ++ ++static void insert_soinfo_into_debug_map(soinfo* info) { ++ // Copy the necessary fields into the debug structure. ++ 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(info->get_realpath()); ++ map->l_ld = info->dynamic; ++ ++ // 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_tail) { ++ r_debug_tail->l_next = map; ++ map->l_prev = r_debug_tail; ++ map->l_next = 0; ++ } else { ++ _r_debug.r_map = map; ++ map->l_prev = 0; ++ map->l_next = 0; ++ } ++ r_debug_tail = map; ++} ++ ++static void remove_soinfo_from_debug_map(soinfo* info) { ++ link_map* map = &(info->link_map_head); ++ ++ if (r_debug_tail == map) { ++ r_debug_tail = map->l_prev; ++ } ++ ++ if (map->l_prev) { ++ map->l_prev->l_next = map->l_next; ++ } ++ if (map->l_next) { ++ map->l_next->l_prev = map->l_prev; ++ } ++} ++ ++static void notify_gdb_of_load(soinfo* info) { ++ if (info->is_main_executable()) { ++ // GDB already knows about the main executable ++ return; ++ } ++ ++ ScopedPthreadMutexLocker locker(&g__r_debug_mutex); ++ ++ _r_debug.r_state = r_debug::RT_ADD; ++ rtld_db_dlactivity(); ++ ++ insert_soinfo_into_debug_map(info); ++ ++ _r_debug.r_state = r_debug::RT_CONSISTENT; ++ rtld_db_dlactivity(); ++} ++ ++static void notify_gdb_of_unload(soinfo* info) { ++ if (info->is_main_executable()) { ++ // GDB already knows about the main executable ++ return; ++ } ++ ++ ScopedPthreadMutexLocker locker(&g__r_debug_mutex); ++ ++ _r_debug.r_state = r_debug::RT_DELETE; ++ rtld_db_dlactivity(); ++ ++ remove_soinfo_from_debug_map(info); ++ ++ _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(); ++} ++ ++LinkedListEntry* SoinfoListAllocator::alloc() { ++ return g_soinfo_links_allocator.alloc(); ++} ++ ++void SoinfoListAllocator::free(LinkedListEntry* entry) { ++ g_soinfo_links_allocator.free(entry); ++} ++ ++static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, ++ off64_t file_offset, uint32_t rtld_flags) { ++ if (strlen(name) >= PATH_MAX) { ++ DL_ERR("library name \"%s\" too long", name); ++ return nullptr; ++ } ++ ++ soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(name, file_stat, file_offset, rtld_flags); ++ ++ sonext->next = si; ++ sonext = 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) { ++ munmap(reinterpret_cast(si->base), si->size); ++ } ++ ++ soinfo *prev = nullptr, *trav; ++ ++ TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si); ++ ++ for (trav = solist; trav != nullptr; trav = trav->next) { ++ if (trav == si) { ++ break; ++ } ++ prev = trav; ++ } ++ ++ if (trav == nullptr) { ++ // si was not in solist ++ DL_ERR("name \"%s\"@%p is not in solist!", si->get_realpath(), si); ++ return; ++ } ++ ++ // clear links to/from si ++ si->remove_all_links(); ++ ++ // prev will never be null, because the first entry in solist is ++ // always the static libdl_info. ++ prev->next = si->next; ++ if (si == sonext) { ++ sonext = prev; ++ } ++ ++ si->~soinfo(); ++ g_soinfo_allocator.free(si); ++} ++ ++static void parse_path(const char* path, const char* delimiters, ++ std::vector* paths) { ++ if (path == nullptr) { ++ return; ++ } ++ ++ paths->clear(); ++ ++ for (const char *p = path; ; ++p) { ++ size_t len = strcspn(p, delimiters); ++ // skip empty tokens ++ if (len == 0) { ++ continue; ++ } ++ ++ paths->push_back(std::string(p, len)); ++ p += len; ++ ++ if (*p == '\0') { ++ break; ++ } ++ } ++} ++ ++static void parse_LD_LIBRARY_PATH(const char* path) { ++ parse_path(path, ":", &g_ld_library_paths); ++} ++ ++static void parse_LD_PRELOAD(const char* path) { ++ // We have historically supported ':' as well as ' ' in LD_PRELOAD. ++ parse_path(path, " :", &g_ld_preload_names); ++} ++ ++static bool realpath_fd(int fd, std::string* realpath) { ++ std::vector 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) { ++ PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd); ++ return false; ++ } ++ ++ *realpath = std::string(&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(). ++// ++// This function is exposed via dlfcn.cpp and libdl.so. ++_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) { ++ uintptr_t addr = reinterpret_cast(pc); ++ ++ for (soinfo* si = solist; si != 0; si = si->next) { ++ if ((addr >= si->base) && (addr < (si->base + si->size))) { ++ *pcount = si->ARM_exidx_count; ++ return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx); ++ } ++ } ++ *pcount = 0; ++ return nullptr; ++} ++ ++#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; 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; ++} ++ ++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; ++} ++ ++template ++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_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(verdef_ptr + verdaux_offset); ++ ++ if (functor(i, verdef, verdaux) == true) { ++ break; ++ } ++ } ++ ++ return true; ++} ++ ++bool soinfo::find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const { ++ if (vi == nullptr) { ++ *versym = kVersymNotNeeded; ++ return true; ++ } ++ ++ *versym = kVersymGlobal; ++ ++ return for_each_verdef(this, ++ [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) { ++ if (verdef->vd_hash == vi->elf_hash && ++ strcmp(vi->name, get_string(verdaux->vda_name)) == 0) { ++ *versym = verdef->vd_ndx; ++ return true; ++ } ++ ++ return false; ++ } ++ ); ++} ++ ++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("unexpected ST_BIND value: %d for '%s' in '%s'", ++ 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(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(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(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(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(s->st_value), ++ static_cast(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(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(base), hash, hash % nbucket_); ++ ++ ElfW(Versym) verneed = 0; ++ if (!find_verdef_version_index(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(s->st_value), ++ static_cast(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(base), hash, hash % nbucket_); ++ ++ *symbol_index = 0; ++ return true; ++} ++ ++soinfo::soinfo(const char* realpath, const struct stat* file_stat, ++ off64_t file_offset, int rtld_flags) { ++ ++ 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; ++} ++ ++ ++uint32_t SymbolName::elf_hash() { ++ if (!has_elf_hash_) { ++ const uint8_t* name = reinterpret_cast(name_); ++ uint32_t h = 0, g; ++ ++ while (*name) { ++ h = (h << 4) + *name++; ++ g = h & 0xf0000000; ++ h ^= g; ++ h ^= g >> 24; ++ } ++ ++ elf_hash_ = h; ++ 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(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_; ++} ++ ++bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi, ++ soinfo** si_found_in, const soinfo::soinfo_list_t& global_group, ++ const soinfo::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(s->st_value), ++ (*si_found_in)->get_realpath(), reinterpret_cast((*si_found_in)->base), ++ reinterpret_cast((*si_found_in)->load_bias)); ++ } ++ ++ *symbol = s; ++ return true; ++} ++ ++class ProtectedDataGuard { ++ public: ++ ProtectedDataGuard() { ++ if (ref_count_++ == 0) { ++ protect_data(PROT_READ | PROT_WRITE); ++ } ++ } ++ ++ ~ProtectedDataGuard() { ++ if (ref_count_ == 0) { // overflow ++ __libc_fatal("Too many nested calls to dlopen()"); ++ } ++ ++ if (--ref_count_ == 0) { ++ protect_data(PROT_READ); ++ } ++ } ++ private: ++ void protect_data(int protection) { ++ g_soinfo_allocator.protect_all(protection); ++ g_soinfo_links_allocator.protect_all(protection); ++ } ++ ++ static size_t ref_count_; ++}; ++ ++size_t ProtectedDataGuard::ref_count_ = 0; ++ ++// Each size has it's own allocator. ++template ++class SizeBasedAllocator { ++ public: ++ static void* alloc() { ++ return allocator_.alloc(); ++ } ++ ++ static void free(void* ptr) { ++ allocator_.free(ptr); ++ } ++ ++ private: ++ static LinkerBlockAllocator allocator_; ++}; ++ ++template ++LinkerBlockAllocator SizeBasedAllocator::allocator_(size); ++ ++template ++class TypeBasedAllocator { ++ public: ++ static T* alloc() { ++ return reinterpret_cast(SizeBasedAllocator::alloc()); ++ } ++ ++ static void free(T* ptr) { ++ SizeBasedAllocator::free(ptr); ++ } ++}; ++ ++class LoadTask { ++ public: ++ struct deleter_t { ++ void operator()(LoadTask* t) { ++ TypeBasedAllocator::free(t); ++ } ++ }; ++ ++ typedef UniquePtr unique_ptr; ++ ++ static deleter_t deleter; ++ ++ static LoadTask* create(const char* name, soinfo* needed_by) { ++ LoadTask* ptr = TypeBasedAllocator::alloc(); ++ return new (ptr) LoadTask(name, needed_by); ++ } ++ ++ const char* get_name() const { ++ return name_; ++ } ++ ++ soinfo* get_needed_by() const { ++ return needed_by_; ++ } ++ private: ++ LoadTask(const char* name, soinfo* needed_by) ++ : name_(name), needed_by_(needed_by) {} ++ ++ const char* name_; ++ soinfo* needed_by_; ++ ++ DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask); ++}; ++ ++LoadTask::deleter_t LoadTask::deleter; ++ ++template ++using linked_list_t = LinkedList>>; ++ ++typedef linked_list_t SoinfoLinkedList; ++typedef linked_list_t StringLinkedList; ++typedef linked_list_t LoadTaskList; ++ ++ ++// 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 false. ++// ++// walk_dependencies_tree returns false if walk was terminated ++// by the action and true otherwise. ++template ++static bool walk_dependencies_tree(soinfo* root_soinfos[], size_t root_soinfos_size, F action) { ++ SoinfoLinkedList visit_list; ++ SoinfoLinkedList visited; ++ ++ for (size_t i = 0; i < root_soinfos_size; ++i) { ++ visit_list.push_back(root_soinfos[i]); ++ } ++ ++ soinfo* si; ++ while ((si = visit_list.pop_front()) != nullptr) { ++ if (visited.contains(si)) { ++ continue; ++ } ++ ++ if (!action(si)) { ++ return false; ++ } ++ ++ visited.push_back(si); ++ ++ si->get_children().for_each([&](soinfo* child) { ++ visit_list.push_back(child); ++ }); ++ } ++ ++ return true; ++} ++ ++ ++static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until, ++ soinfo** found, SymbolName& symbol_name) { ++ const ElfW(Sym)* result = nullptr; ++ bool skip_lookup = skip_until != nullptr; ++ ++ walk_dependencies_tree(&root, 1, [&](soinfo* current_soinfo) { ++ if (skip_lookup) { ++ skip_lookup = current_soinfo != skip_until; ++ return true; ++ } ++ ++ if (!current_soinfo->find_symbol_by_name(symbol_name, nullptr, &result)) { ++ result = nullptr; ++ return false; ++ } ++ ++ if (result != nullptr) { ++ *found = current_soinfo; ++ return false; ++ } ++ ++ return true; ++ }); ++ ++ return result; ++} ++ ++// This is used by dlsym(3). It performs symbol lookup only within the ++// specified soinfo object and its dependencies in breadth first order. ++const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) { ++ // 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 == somain) { ++ return dlsym_linear_lookup(name, found, nullptr, RTLD_DEFAULT); ++ } ++ ++ SymbolName symbol_name(name); ++ return dlsym_handle_lookup(si, nullptr, found, symbol_name); ++} ++ ++/* 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). ++ */ ++const ElfW(Sym)* dlsym_linear_lookup(const char* name, ++ soinfo** found, ++ soinfo* caller, ++ void* handle) { ++ SymbolName symbol_name(name); ++ ++ soinfo* start = solist; ++ ++ if (handle == RTLD_NEXT) { ++ if (caller == nullptr) { ++ return nullptr; ++ } else { ++ start = caller->next; ++ } ++ } ++ ++ const ElfW(Sym)* s = nullptr; ++ for (soinfo* si = start; si != nullptr; si = si->next) { ++ // Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...) ++ // if the library is opened by application with target api level <= 22 ++ // See http://b/21565766 ++ if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0 && si->get_target_sdk_version() > 22) { ++ continue; ++ } ++ ++ if (!si->find_symbol_by_name(symbol_name, nullptr, &s)) { ++ return nullptr; ++ } ++ ++ if (s != nullptr) { ++ *found = si; ++ break; ++ } ++ } ++ ++ // If not found - use dlsym_handle_lookup for caller's ++ // local_group unless it is part of the global group in which ++ // case we already did it. ++ if (s == nullptr && caller != nullptr && ++ (caller->get_rtld_flags() & RTLD_GLOBAL) == 0) { ++ return dlsym_handle_lookup(caller->get_local_group_root(), ++ (handle == RTLD_NEXT) ? caller : nullptr, found, symbol_name); ++ } ++ ++ if (s != nullptr) { ++ TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p", ++ name, reinterpret_cast(s->st_value), reinterpret_cast((*found)->base)); ++ } ++ ++ return s; ++} ++ ++soinfo* find_containing_library(const void* p) { ++ ElfW(Addr) address = reinterpret_cast(p); ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ if (address >= si->base && address - si->base < si->size) { ++ return si; ++ } ++ } ++ return nullptr; ++} ++ ++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) { ++ return sym->st_shndx != SHN_UNDEF && ++ 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(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(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 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(buf_size)) { ++ PRINT("Warning: ignoring very long library path: %s/%s", path, name); ++ return false; ++ } ++ ++ return true; ++} ++ ++static int open_library_on_default_path(const char* name, off64_t* file_offset) { ++ for (size_t i = 0; kDefaultLdPaths[i] != nullptr; ++i) { ++ char buf[512]; ++ if (!format_path(buf, sizeof(buf), kDefaultLdPaths[i], name)) { ++ continue; ++ } ++ ++ int fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC)); ++ if (fd != -1) { ++ *file_offset = 0; ++ return fd; ++ } ++ } ++ ++ return -1; ++} ++ ++static int open_library_on_ld_library_path(const char* name, off64_t* file_offset) { ++ for (const auto& path_str : g_ld_library_paths) { ++ char buf[512]; ++ const char* const path = path_str.c_str(); ++ if (!format_path(buf, sizeof(buf), path, name)) { ++ continue; ++ } ++ ++ int fd = -1; ++ if (fd == -1) { ++ fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC)); ++ if (fd != -1) { ++ *file_offset = 0; ++ } ++ } ++ ++ if (fd != -1) { ++ return fd; ++ } ++ } ++ ++ return -1; ++} ++ ++static int open_library(const char* name, off64_t* file_offset) { ++ TRACE("[ opening %s ]", 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 = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC)); ++ if (fd != -1) { ++ *file_offset = 0; ++ } ++ return fd; ++ } ++ ++ // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths. ++ int fd = open_library_on_ld_library_path(name, file_offset); ++ if (fd == -1) { ++ fd = open_library_on_default_path(name, file_offset); ++ } ++ return fd; ++} ++ ++static const char* fix_dt_needed(const char* dt_needed, const char* sopath) { ++ (void) sopath; ++#if !defined(__LP64__) ++ // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029 ++ if (get_application_target_sdk_version() <= 22) { ++ const char* bname = basename(dt_needed); ++ if (bname != dt_needed) { ++ DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed); ++ } ++ ++ return bname; ++ } ++#endif ++ return dt_needed; ++} ++ ++template ++static void for_each_dt_needed(const soinfo* si, F action) { ++ for (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())); ++ } ++ } ++} ++ ++static soinfo* load_library(int fd, off64_t file_offset, ++ LoadTaskList& load_tasks, ++ const char* name, int rtld_flags, ++ const android_dlextinfo* extinfo) { ++ if ((file_offset % PAGE_SIZE) != 0) { ++ DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset); ++ return nullptr; ++ } ++ if (file_offset < 0) { ++ DL_ERR("file offset for the library \"%s\" is negative: %" PRId64, name, file_offset); ++ return nullptr; ++ } ++ ++ struct stat file_stat; ++ if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) { ++ DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno)); ++ return nullptr; ++ } ++ 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 nullptr; ++ } ++ ++ // 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) { ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ if (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) { ++ TRACE("library \"%s\" is already loaded under different name/path \"%s\" - " ++ "will return existing soinfo", name, si->get_realpath()); ++ return si; ++ } ++ } ++ } ++ ++ if ((rtld_flags & RTLD_NOLOAD) != 0) { ++ DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name); ++ return nullptr; ++ } ++ ++ std::string realpath = name; ++ if (!realpath_fd(fd, &realpath)) { ++ PRINT("warning: unable to get realpath for the library \"%s\". Will use given name.", name); ++ realpath = name; ++ } ++ ++ // Read the ELF header and load the segments. ++ ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size); ++ if (!elf_reader.Load(extinfo)) { ++ return nullptr; ++ } ++ ++ soinfo* si = soinfo_alloc(realpath.c_str(), &file_stat, file_offset, rtld_flags); ++ if (si == nullptr) { ++ return nullptr; ++ } ++ si->base = elf_reader.load_start(); ++ si->size = elf_reader.load_size(); ++ si->load_bias = elf_reader.load_bias(); ++ si->phnum = elf_reader.phdr_count(); ++ si->phdr = elf_reader.loaded_phdr(); ++ ++ if (!si->prelink_image()) { ++ soinfo_free(si); ++ return nullptr; ++ } ++ ++ for_each_dt_needed(si, [&] (const char* name) { ++ load_tasks.push_back(LoadTask::create(name, si)); ++ }); ++ ++ return si; ++} ++ ++static soinfo* load_library(LoadTaskList& load_tasks, ++ const char* name, int rtld_flags, ++ const android_dlextinfo* extinfo) { ++ if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) { ++ off64_t file_offset = 0; ++ if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) { ++ file_offset = extinfo->library_fd_offset; ++ } ++ return load_library(extinfo->library_fd, file_offset, load_tasks, name, rtld_flags, extinfo); ++ } ++ ++ // Open the file. ++ off64_t file_offset; ++ int fd = open_library(name, &file_offset); ++ if (fd == -1) { ++ DL_ERR("library \"%s\" not found", name); ++ return nullptr; ++ } ++ soinfo* result = load_library(fd, file_offset, load_tasks, name, rtld_flags, extinfo); ++ close(fd); ++ return result; ++} ++ ++// Returns true if library was found and false in 2 cases ++// 1. The library was found but loaded under different target_sdk_version ++// (*candidate != nullptr) ++// 2. The library was not found by soname (*candidate is nullptr) ++static bool find_loaded_library_by_soname(const char* name, soinfo** candidate) { ++ *candidate = nullptr; ++ ++ // Ignore filename with path. ++ if (strchr(name, '/') != nullptr) { ++ return false; ++ } ++ ++ uint32_t target_sdk_version = get_application_target_sdk_version(); ++ ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ const char* soname = si->get_soname(); ++ if (soname != nullptr && (strcmp(name, soname) == 0)) { ++ // If the library was opened under different target sdk version ++ // skip this step and try to reopen it. The exceptions are ++ // "libdl.so" and global group. There is no point in skipping ++ // them because relocation process is going to use them ++ // in any case. ++ bool is_libdl = si == solist; ++ if (is_libdl || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0 || ++ !si->is_linked() || si->get_target_sdk_version() == target_sdk_version) { ++ *candidate = si; ++ return true; ++ } else if (*candidate == nullptr) { ++ // for the different sdk version - remember the first library. ++ *candidate = si; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name, ++ int rtld_flags, const android_dlextinfo* extinfo) { ++ soinfo* candidate; ++ ++ if (find_loaded_library_by_soname(name, &candidate)) { ++ return candidate; ++ } ++ ++ // Library might still be loaded, the accurate detection ++ // of this fact is done by load_library. ++ TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]", ++ name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate); ++ ++ soinfo* si = load_library(load_tasks, name, rtld_flags, extinfo); ++ ++ // In case we were unable to load the library but there ++ // is a candidate loaded under the same soname but different ++ // sdk level - return it anyways. ++ if (si == nullptr && candidate != nullptr) { ++ si = candidate; ++ } ++ ++ return si; ++} ++ ++static void soinfo_unload(soinfo* 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. ++static soinfo::soinfo_list_t make_global_group() { ++ soinfo::soinfo_list_t global_group; ++ for (soinfo* si = somain; si != nullptr; si = si->next) { ++ if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) { ++ global_group.push_back(si); ++ } ++ } ++ ++ return global_group; ++} ++ ++static bool find_libraries(soinfo* start_with, const char* const library_names[], ++ size_t library_names_count, soinfo* soinfos[], std::vector* ld_preloads, ++ size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) { ++ // Step 0: prepare. ++ 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)); ++ } ++ ++ // Construct global_group. ++ soinfo::soinfo_list_t global_group = make_global_group(); ++ ++ // 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(alloca(soinfos_size)); ++ memset(soinfos, 0, soinfos_size); ++ } ++ ++ // list of libraries to link - see step 2. ++ size_t soinfos_count = 0; ++ ++ auto failure_guard = make_scope_guard([&]() { ++ // Housekeeping ++ load_tasks.for_each([] (LoadTask* t) { ++ LoadTask::deleter(t); ++ }); ++ ++ for (size_t i = 0; iget_name(), rtld_flags, extinfo); ++ if (si == nullptr) { ++ return false; ++ } ++ ++ soinfo* needed_by = task->get_needed_by(); ++ ++ if (needed_by != nullptr) { ++ needed_by->add_child(si); ++ } ++ ++ if (si->is_linked()) { ++ si->increment_ref_count(); ++ } ++ ++ // 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) { ++ // Add LD_PRELOADed libraries to the global group for future runs. ++ // There is no need to explicitly add them to the global group ++ // for this run because they are going to appear in the local ++ // group in the correct order. ++ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL); ++ ld_preloads->push_back(si); ++ } ++ ++ if (soinfos_count < library_names_count) { ++ soinfos[soinfos_count++] = si; ++ } ++ } ++ ++ // Step 2: link libraries. ++ soinfo::soinfo_list_t local_group; ++ walk_dependencies_tree( ++ start_with == nullptr ? soinfos : &start_with, ++ start_with == nullptr ? soinfos_count : 1, ++ [&] (soinfo* si) { ++ local_group.push_back(si); ++ return true; ++ }); ++ ++ // We need to increment ref_count in case ++ // the root of the local group was not linked. ++ bool was_local_group_root_linked = local_group.front()->is_linked(); ++ ++ bool linked = local_group.visit([&](soinfo* si) { ++ if (!si->is_linked()) { ++ if (!si->link_image(global_group, local_group, extinfo)) { ++ return false; ++ } ++ si->set_linked(); ++ } ++ ++ return true; ++ }); ++ ++ if (linked) { ++ failure_guard.disable(); ++ } ++ ++ if (!was_local_group_root_linked) { ++ local_group.front()->increment_ref_count(); ++ } ++ ++ return linked; ++} ++ ++static soinfo* find_library(const char* name, int rtld_flags, const android_dlextinfo* extinfo) { ++ soinfo* si; ++ ++ if (name == nullptr) { ++ si = somain; ++ } else if (!find_libraries(nullptr, &name, 1, &si, nullptr, 0, rtld_flags, extinfo)) { ++ return nullptr; ++ } ++ ++ return si; ++} ++ ++static void soinfo_unload(soinfo* root) { ++ // 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. ++ if (root->is_linked()) { ++ root = root->get_local_group_root(); ++ } ++ ++ if (!root->can_unload()) { ++ TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath()); ++ return; ++ } ++ ++ size_t ref_count = root->is_linked() ? root->decrement_ref_count() : 0; ++ ++ if (ref_count == 0) { ++ soinfo::soinfo_list_t local_unload_list; ++ soinfo::soinfo_list_t external_unload_list; ++ soinfo::soinfo_list_t depth_first_list; ++ depth_first_list.push_back(root); ++ soinfo* si = nullptr; ++ ++ while ((si = depth_first_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); ++ ++ 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 { ++ depth_first_list.push_front(child); ++ } ++ } ++ } else { ++#if !defined(__work_around_b_19059885__) ++ __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si); ++#else ++ PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si); ++ for_each_dt_needed(si, [&] (const char* library_name) { ++ TRACE("deprecated (old format of soinfo): %s needs to unload %s", ++ si->get_realpath(), library_name); ++ ++ soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr); ++ if (needed != nullptr) { ++ // Not found: for example if symlink was deleted between dlopen and dlclose ++ // Since we cannot really handle errors at this point - print and continue. ++ PRINT("warning: couldn't find %s needed by %s on unload.", ++ library_name, si->get_realpath()); ++ return; ++ } else if (local_unload_list.contains(needed)) { ++ // already visited ++ return; ++ } else if (needed->is_linked() && needed->get_local_group_root() != root) { ++ // external group ++ external_unload_list.push_back(needed); ++ } else { ++ // local group ++ depth_first_list.push_front(needed); ++ } ++ }); ++#endif ++ } ++ } ++ ++ local_unload_list.for_each([](soinfo* si) { ++ si->call_destructors(); ++ }); ++ ++ while ((si = local_unload_list.pop_front()) != nullptr) { ++ notify_gdb_of_unload(si); ++ soinfo_free(si); ++ } ++ ++ while ((si = external_unload_list.pop_front()) != nullptr) { ++ soinfo_unload(si); ++ } ++ } else { ++ TRACE("not unloading '%s' group, decrementing ref_count to %zd", ++ root->get_realpath(), ref_count); ++ } ++} ++ ++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. ++ size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2; ++ if (buffer_size < required_len) { ++ __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: " ++ "buffer len %zu, required len %zu", buffer_size, required_len); ++ } ++ char* end = stpcpy(buffer, kDefaultLdPaths[0]); ++ *end = ':'; ++ strcpy(end + 1, kDefaultLdPaths[1]); ++} ++ ++void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) { ++ parse_LD_LIBRARY_PATH(ld_library_path); ++} ++ ++soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) { ++ 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; ++ } ++ } ++ ++ ProtectedDataGuard guard; ++ soinfo* si = find_library(name, flags, extinfo); ++ if (si != nullptr) { ++ si->call_constructors(); ++ } ++ return si; ++} ++ ++void do_dlclose(soinfo* si) { ++ ProtectedDataGuard guard; ++ soinfo_unload(si); ++} ++ ++static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) { ++ typedef ElfW(Addr) (*ifunc_resolver_t)(void); ++ ifunc_resolver_t ifunc_resolver = reinterpret_cast(resolver_addr); ++ ElfW(Addr) ifunc_addr = ifunc_resolver(); ++ TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p", ++ ifunc_resolver, reinterpret_cast(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_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; jvn_cnt; ++j) { ++ const ElfW(Vernaux)* vernaux = reinterpret_cast(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; ++} ++ ++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); ++} ++ ++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; ++} ++ ++#if !defined(__mips__) ++#if defined(USE_RELA) ++static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr ) { ++ 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) { ++ return *reinterpret_cast(reloc_addr); ++ } ++ return 0; ++} ++#endif ++ ++template ++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(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) { ++ sym_name = get_string(symtab_[sym].st_name); ++ const version_info* vi = nullptr; ++ ++ sym_addr = reinterpret_cast(_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; ++ } ++ } ++ ++ 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: ++#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 ++ sym_addr = lsi->resolve_symbol_address(s); ++#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(reloc), ++ reinterpret_cast(sym_addr + addend), sym_name); ++ ++ *reinterpret_cast(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(reloc), ++ reinterpret_cast(sym_addr + addend), sym_name); ++ *reinterpret_cast(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(reloc), ++ reinterpret_cast(load_bias + addend)); ++ *reinterpret_cast(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(reloc), ++ reinterpret_cast(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(reloc) = ifunc_addr; ++ } ++ break; ++ ++#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(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) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT32_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT32_MAX); ++ if ((min_value <= (reloc_value + (sym_addr + addend))) && ++ ((reloc_value + (sym_addr + addend)) <= max_value)) { ++ *reinterpret_cast(reloc) += (sym_addr + addend); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ (reloc_value + (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) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT16_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT16_MAX); ++ if ((min_value <= (reloc_value + (sym_addr + addend))) && ++ ((reloc_value + (sym_addr + addend)) <= max_value)) { ++ *reinterpret_cast(reloc) += (sym_addr + addend); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ reloc_value + (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(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) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT32_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT32_MAX); ++ if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) && ++ ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) { ++ *reinterpret_cast(reloc) += ((sym_addr + addend) - rel->r_offset); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ reloc_value + ((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) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT16_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT16_MAX); ++ if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) && ++ ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) { ++ *reinterpret_cast(reloc) += ((sym_addr + addend) - rel->r_offset); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ reloc_value + ((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; ++ case R_AARCH64_TLS_TPREL: ++ TRACE_TYPE(RELO, "RELO TLS_TPREL *** %16llx <- %16llx - %16llx\n", ++ reloc, (sym_addr + addend), rel->r_offset); ++ break; ++ case R_AARCH64_TLS_DTPREL: ++ TRACE_TYPE(RELO, "RELO TLS_DTPREL *** %16llx <- %16llx - %16llx\n", ++ reloc, (sym_addr + addend), rel->r_offset); ++ break; ++#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(reloc), ++ static_cast(sym_addr), sym_name); ++ *reinterpret_cast(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(reloc), ++ static_cast(sym_addr), sym_name); ++ *reinterpret_cast(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(reloc), static_cast(sym_addr - reloc), ++ static_cast(sym_addr), static_cast(reloc), sym_name); ++ *reinterpret_cast(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(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(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(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(reloc) += (sym_addr - reloc); ++ break; ++#endif ++ default: ++ DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx); ++ return false; ++ } ++ } ++ return true; ++} ++#endif // !defined(__mips__) ++ ++void soinfo::call_array(const char* array_name , linker_function_t* functions, ++ size_t count, bool reverse) { ++ if (functions == nullptr) { ++ return; ++ } ++ ++ TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_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]); ++ } ++ ++ TRACE("[ Done calling %s for '%s' ]", array_name, get_realpath()); ++} ++ ++void soinfo::call_function(const char* function_name , linker_function_t function) { ++ if (function == nullptr || reinterpret_cast(function) == static_cast(-1)) { ++ return; ++ } ++ ++ TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_realpath()); ++ function(); ++ TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_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); ++} ++ ++void soinfo::call_constructors() { ++ if (constructors_called) { ++ return; ++ } ++ ++ if (strcmp(soname_, "libc.so") == 0) { ++ DEBUG("HYBRIS: =============> Skipping libc.so\n"); ++ 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 %zd-entry DT_PREINIT_ARRAY in shared library!", ++ get_realpath(), preinit_array_count_); ++ } ++ ++ get_children().for_each([] (soinfo* si) { ++ si->call_constructors(); ++ }); ++ ++ TRACE("\"%s\": calling constructors", get_realpath()); ++ ++ // DT_INIT should be called before DT_INIT_ARRAY if both are present. ++ call_function("DT_INIT", init_func_); ++ call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false); ++} ++ ++void soinfo::call_destructors() { ++ if (!constructors_called) { ++ return; ++ } ++ TRACE("\"%s\": calling destructors", get_realpath()); ++ ++ // DT_FINI_ARRAY must be parsed in reverse order. ++ call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true); ++ ++ // DT_FINI should be called after DT_FINI_ARRAY if both are present. ++ call_function("DT_FINI", fini_func_); ++ ++ // This is needed on second call to dlopen ++ // after library has been unloaded with RTLD_NODELETE ++ constructors_called = false; ++} ++ ++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. Once everything untied - clear local lists. ++ parents_.clear(); ++ children_.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; ++ } ++} ++ ++const char* soinfo::get_realpath() const { ++#if defined(__work_around_b_19059885__) ++ if (has_min_version(2)) { ++ return realpath_.c_str(); ++ } else { ++ return old_name_; ++ } ++#else ++ return realpath_.c_str(); ++#endif ++} ++ ++const char* soinfo::get_soname() const { ++#if defined(__work_around_b_19059885__) ++ 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::soinfo_list_t g_empty_list; ++ ++soinfo::soinfo_list_t& soinfo::get_children() { ++ if (has_min_version(0)) { ++ return children_; ++ } ++ ++ return g_empty_list; ++} ++ ++const soinfo::soinfo_list_t& soinfo::get_children() const { ++ if (has_min_version(0)) { ++ return children_; ++ } ++ ++ return g_empty_list; ++} ++ ++soinfo::soinfo_list_t& soinfo::get_parents() { ++ if (has_min_version(0)) { ++ return parents_; ++ } ++ ++ return g_empty_list; ++} ++ ++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(s->st_value + load_bias); ++} ++ ++const char* soinfo::get_string(ElfW(Word) index) const { ++ if (has_min_version(1) && (index >= strtab_size_)) { ++ __libc_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 (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0; ++} ++ ++bool soinfo::is_linked() const { ++ return (flags_ & FLAG_LINKED) != 0; ++} ++ ++bool soinfo::is_main_executable() const { ++ return (flags_ & FLAG_EXE) != 0; ++} ++ ++void soinfo::set_linked() { ++ flags_ |= FLAG_LINKED; ++} ++ ++void soinfo::set_linker_flag() { ++ flags_ |= FLAG_LINKER; ++} ++ ++void soinfo::set_main_executable() { ++ flags_ |= FLAG_EXE; ++} ++ ++void soinfo::increment_ref_count() { ++ local_group_root_->ref_count_++; ++} ++ ++size_t soinfo::decrement_ref_count() { ++ return --local_group_root_->ref_count_; ++} ++ ++soinfo* soinfo::get_local_group_root() const { ++ return local_group_root_; ++} ++ ++// This function returns api-level at the time of ++// dlopen/load. Note that libraries opened by system ++// will always have 'current' api level. ++uint32_t soinfo::get_target_sdk_version() const { ++ if (!has_min_version(2)) { ++ return __ANDROID_API__; ++ } ++ ++ return local_group_root_->target_sdk_version_; ++} ++ ++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(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 ++ ++ // 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(d->d_tag), reinterpret_cast(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(load_bias + d->d_un.d_ptr)[0]; ++ nchain_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[1]; ++ bucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 8); ++ chain_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4); ++ break; ++ ++ case DT_GNU_HASH: ++ gnu_nbucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[0]; ++ // skip symndx ++ gnu_maskwords_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[2]; ++ gnu_shift2_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[3]; ++ ++ gnu_bloom_filter_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 16); ++ gnu_bucket_ = reinterpret_cast(gnu_bloom_filter_ + gnu_maskwords_); ++ // amend chain for symndx = header[1] ++ gnu_chain_ = gnu_bucket_ + gnu_nbucket_ - ++ reinterpret_cast(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(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(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(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(load_bias + d->d_un.d_ptr); ++#else ++ plt_rel_ = reinterpret_cast(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(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(&_r_debug); ++ } ++#endif ++ break; ++#if defined(USE_RELA) ++ case DT_RELA: ++ rela_ = reinterpret_cast(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(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(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(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(d->d_un.d_val)); ++ return false; ++ } ++ break; ++ ++ case DT_ANDROID_REL: ++ android_relocs_ = reinterpret_cast(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_INIT: ++ init_func_ = reinterpret_cast(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(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(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(d->d_un.d_val) / sizeof(ElfW(Addr)); ++ break; ++ ++ case DT_FINI_ARRAY: ++ fini_array_ = reinterpret_cast(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(d->d_un.d_val) / sizeof(ElfW(Addr)); ++ break; ++ ++ case DT_PREINIT_ARRAY: ++ preinit_array_ = reinterpret_cast(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(d->d_un.d_val) / sizeof(ElfW(Addr)); ++ break; ++ ++ case DT_TEXTREL: ++#if defined(__LP64__) ++ DL_ERR("text relocations (DT_TEXTREL) found in 64-bit ELF file \"%s\"", 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("text relocations (DF_TEXTREL) found in 64-bit ELF file \"%s\"", 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("%s: unsupported flags DT_FLAGS_1=%p", get_realpath(), reinterpret_cast(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(load_bias + d->d_un.d_ptr); ++ *dp = &_r_debug; ++ } ++ break; ++ case DT_MIPS_RLD_MAP2: ++ // Set the DT_MIPS_RLD_MAP2 entry to the address of _r_debug for GDB. ++ { ++ r_debug** dp = reinterpret_cast( ++ reinterpret_cast(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(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; ++ ++ default: ++ if (!relocating_linker) { ++ DL_WARN("%s: unused DT entry: type %p arg %p", get_realpath(), ++ reinterpret_cast(d->d_tag), reinterpret_cast(d->d_un.d_val)); ++ } ++ break; ++ } ++ } ++ ++ DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p", ++ reinterpret_cast(base), strtab_, symtab_); ++ ++ // Sanity checks. ++ if (relocating_linker && needed_count != 0) { ++ DL_ERR("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_ == 0) { ++ DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath()); ++ return false; ++ } ++ if (symtab_ == 0) { ++ 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) { ++ if (d->d_tag == DT_SONAME) { ++ soname_ = get_string(d->d_un.d_val); ++#if defined(__work_around_b_19059885__) ++ strlcpy(old_name_, soname_, sizeof(old_name_)); ++#endif ++ 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 <=22). Make an exception for ++ // the main executable and linker; they do not need to have dt_soname ++ if (soname_ == nullptr && this != somain && (flags_ & FLAG_LINKER) == 0 && ++ get_application_target_sdk_version() <= 22) { ++ soname_ = basename(realpath_.c_str()); ++ DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"", ++ get_realpath(), soname_); ++ } ++ return true; ++} ++ ++bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, ++ const android_dlextinfo* extinfo) { ++ ++ 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 sdk version > 22 ++ // TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed ++ if (get_application_target_sdk_version() != __ANDROID_API__ ++ && get_application_target_sdk_version() > 22) { ++ DL_ERR("%s: has text relocations", 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 and all constructors are run. ++ DL_WARN("%s has text relocations. This is wasting memory and prevents " ++ "security hardening. Please fix.", get_realpath()); ++ 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(packed_relocs, packed_relocs_size)), ++ global_group, local_group); ++ ++ if (!relocated) { ++ return false; ++ } ++ } else { ++ DL_ERR("bad android relocation header."); ++ return false; ++ } ++ } ++ ++#if defined(USE_RELA) ++ if (rela_ != nullptr) { ++ DEBUG("[ relocating %s ]", 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 ]", 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 ]", 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 ]", 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 (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; ++ } ++ ++ /* 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) < 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) < 0) { ++ DL_ERR("failed mapping GNU RELRO section for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++ ++ notify_gdb_of_load(this); ++ return true; ++} ++ ++/* ++ * This function add vdso to internal dso list. ++ * It helps to stack unwinding through signal handlers. ++ * Also, it makes bionic more like glibc. ++ */ ++static void add_vdso(KernelArgumentBlock& args) { ++#if defined(AT_SYSINFO_EHDR) ++ ElfW(Ehdr)* ehdr_vdso = reinterpret_cast(args.getauxval(AT_SYSINFO_EHDR)); ++ if (ehdr_vdso == nullptr) { ++ return; ++ } ++ ++ soinfo* si = soinfo_alloc("[vdso]", nullptr, 0, 0); ++ ++ si->phdr = reinterpret_cast(reinterpret_cast(ehdr_vdso) + ehdr_vdso->e_phoff); ++ si->phnum = ehdr_vdso->e_phnum; ++ si->base = reinterpret_cast(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::soinfo_list_t::make_list(si), nullptr); ++#endif ++} ++ ++/* ++ * This is linker soinfo for GDB. See details below. ++ */ ++#if defined(__LP64__) ++#define LINKER_PATH "/system/bin/linker64" ++#else ++#define LINKER_PATH "/system/bin/linker" ++#endif ++ ++// This is done to avoid calling c-tor prematurely ++// because soinfo c-tor needs memory allocator ++// which might be initialized after global variables. ++static uint8_t linker_soinfo_for_gdb_buf[sizeof(soinfo)] __attribute__((aligned(8))); ++static soinfo* linker_soinfo_for_gdb = nullptr; ++ ++/* 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. ++ * Don't use soinfo_alloc(), because the linker shouldn't ++ * be on the soinfo list. ++ */ ++static void init_linker_info_for_gdb(ElfW(Addr) linker_base) { ++ linker_soinfo_for_gdb = new (linker_soinfo_for_gdb_buf) soinfo(LINKER_PATH, nullptr, 0, 0); ++ ++ linker_soinfo_for_gdb->load_bias = linker_base; ++ ++ /* ++ * Set the dynamic field in the link map otherwise gdb will complain with ++ * the following: ++ * warning: .dynamic section for "/system/bin/linker" is not at the ++ * expected address (wrong library or version mismatch?) ++ */ ++ ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_base); ++ ElfW(Phdr)* phdr = reinterpret_cast(linker_base + elf_hdr->e_phoff); ++ phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base, ++ &linker_soinfo_for_gdb->dynamic, nullptr); ++ insert_soinfo_into_debug_map(linker_soinfo_for_gdb); ++} ++ ++extern "C" int __system_properties_init(void); ++ ++/* ++ * This code is called after the linker has linked itself and ++ * fixed it's own GOT. It is safe to make references to externs ++ * and other non-local data at this point. ++ */ ++static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) { ++#if TIMING ++ struct timeval t0, t1; ++ gettimeofday(&t0, 0); ++#endif ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ // Sanitize the environment. ++ __libc_init_AT_SECURE(args); ++ ++ // Initialize system properties ++ __system_properties_init(); // may use 'environ' ++#endif ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ debuggerd_init(); ++#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); ++ } ++ ++ // 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("HYBRIS_LD_LIBRARY_PATH"); ++ ldpreload_env = getenv("HYBRIS_LD_PRELOAD"); ++ } ++ ++ INFO("[ android linker & debugger ]"); ++ ++ soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL); ++ if (si == nullptr) { ++ exit(EXIT_FAILURE); ++ } ++ ++ /* bootstrap the link map, the main exe always needs to be first */ ++ si->set_main_executable(); ++ link_map* map = &(si->link_map_head); ++ ++ map->l_addr = 0; ++ map->l_name = args.argv[0]; ++ map->l_prev = nullptr; ++ map->l_next = nullptr; ++ ++ _r_debug.r_map = map; ++ r_debug_tail = map; ++ ++ init_linker_info_for_gdb(linker_base); ++ ++ // Extract information passed from the kernel. ++ si->phdr = reinterpret_cast(args.getauxval(AT_PHDR)); ++ si->phnum = args.getauxval(AT_PHNUM); ++ si->entry = args.getauxval(AT_ENTRY); ++ ++ /* Compute the value of si->base. We can't rely on the fact that ++ * the first entry is the PHDR because this will not be true ++ * for certain executables (e.g. some in the NDK unit test suite) ++ */ ++ si->base = 0; ++ si->size = phdr_table_get_load_size(si->phdr, si->phnum); ++ si->load_bias = 0; ++ for (size_t i = 0; i < si->phnum; ++i) { ++ if (si->phdr[i].p_type == PT_PHDR) { ++ si->load_bias = reinterpret_cast(si->phdr) - si->phdr[i].p_vaddr; ++ si->base = reinterpret_cast(si->phdr) - si->phdr[i].p_offset; ++ break; ++ } ++ } ++ si->dynamic = nullptr; ++ ++ ElfW(Ehdr)* elf_hdr = reinterpret_cast(si->base); ++ if (elf_hdr->e_type != ET_DYN) { ++ fprintf(stderr, "error: only position independent executables (PIE) are supported.\n"); ++ exit(EXIT_FAILURE); ++ } ++ ++ // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid). ++ if (DEFAULT_HYBRIS_LD_LIBRARY_PATH) ++ parse_LD_LIBRARY_PATH(DEFAULT_HYBRIS_LD_LIBRARY_PATH); ++ else ++ parse_LD_LIBRARY_PATH(ldpath_env); ++ parse_LD_PRELOAD(ldpreload_env); ++ ++ somain = si; ++ ++ if (!si->prelink_image()) { ++ fprintf(stderr, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); ++ exit(EXIT_FAILURE); ++ } ++ ++ // add somain to global group ++ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL); ++ ++ // Load ld_preloads and dependencies. ++ StringLinkedList needed_library_name_list; ++ size_t needed_libraries_count = 0; ++ 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()); ++ ++needed_libraries_count; ++ ++ld_preloads_count; ++ } ++ ++ for_each_dt_needed(si, [&](const char* name) { ++ needed_library_name_list.push_back(name); ++ ++needed_libraries_count; ++ }); ++ ++ const char* needed_library_names[needed_libraries_count]; ++ ++ memset(needed_library_names, 0, sizeof(needed_library_names)); ++ needed_library_name_list.copy_to_array(needed_library_names, needed_libraries_count); ++ ++ if (needed_libraries_count > 0 && ++ !find_libraries(si, needed_library_names, needed_libraries_count, nullptr, ++ &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr)) { ++ fprintf(stderr, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); ++ exit(EXIT_FAILURE); ++ } else if (needed_libraries_count == 0) { ++ if (!si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr)) { ++ fprintf(stderr, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); ++ exit(EXIT_FAILURE); ++ } ++ si->increment_ref_count(); ++ } ++ ++ add_vdso(args); ++ ++ { ++ ProtectedDataGuard guard; ++ ++ si->call_pre_init_constructors(); ++ ++ /* After the prelink_image, the si->load_bias is initialized. ++ * For so lib, the map->l_addr will be updated in notify_gdb_of_load. ++ * We need to update this value for so exe here. So Unwind_Backtrace ++ * for some arch like x86 could work correctly within so exe. ++ */ ++ map->l_addr = si->load_bias; ++ si->call_constructors(); ++ } ++ ++#if TIMING ++ gettimeofday(&t1, nullptr); ++ PRINT("LINKER TIME: %s: %d microseconds", args.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", args.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)", args.argv[0], count, count * 4); ++ } ++#endif ++ ++#if TIMING || STATS || COUNT_PAGES ++ fflush(stdout); ++#endif ++ ++ TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast(si->entry)); ++ return si->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(reinterpret_cast(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(elf) + phdr->p_offset - phdr->p_vaddr; ++ } ++ } ++ return 0; ++} ++ ++extern "C" void android_linker_init(int sdk_version, void* (*get_hooked_symbol)(const char*, const char*)) { ++ // Get a few environment variables. ++ const char* LD_DEBUG = getenv("HYBRIS_LD_DEBUG"); ++ if (LD_DEBUG != nullptr) { ++ g_ld_debug_verbosity = atoi(LD_DEBUG); ++ } ++ ++ if (sdk_version > 0) ++ set_application_target_sdk_version(sdk_version); ++ ++ _get_hooked_symbol = get_hooked_symbol; ++} ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++extern "C" void _start(); ++ ++/* ++ * 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) { ++ KernelArgumentBlock args(raw_args); ++ ++ ElfW(Addr) linker_addr = args.getauxval(AT_BASE); ++ ElfW(Addr) entry_point = args.getauxval(AT_ENTRY); ++ ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_addr); ++ ElfW(Phdr)* phdr = reinterpret_cast(linker_addr + elf_hdr->e_phoff); ++ ++ soinfo linker_so(nullptr, nullptr, 0, 0); ++ ++ // If the linker is not acting as PT_INTERP entry_point is equal to ++ // _start. Which means that the linker is running as an executable and ++ // already linked by PT_INTERP. ++ // ++ // This happens when user tries to run 'adb shell /system/bin/linker' ++ // see also https://code.google.com/p/android/issues/detail?id=63174 ++ if (reinterpret_cast(&_start) == entry_point) { ++ __libc_fatal("This is %s, the helper program for shared library executables.\n", args.argv[0]); ++ } ++ ++ linker_so.base = linker_addr; ++ linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum); ++ linker_so.load_bias = get_elf_exec_load_bias(elf_hdr); ++ linker_so.dynamic = nullptr; ++ linker_so.phdr = phdr; ++ linker_so.phnum = elf_hdr->e_phnum; ++ linker_so.set_linker_flag(); ++ ++ // 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 (!(linker_so.prelink_image() && linker_so.link_image(g_empty_list, g_empty_list, nullptr))) { ++ // It would be nice to print an error message, but if the linker ++ // can't link itself, there's no guarantee that we'll be able to ++ // call write() (because it involves a GOT reference). We may as ++ // well try though... ++ const char* msg = "CANNOT LINK EXECUTABLE: "; ++ int unused __attribute__((unused)); ++ unused = write(2, msg, strlen(msg)); ++ unused = write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf)); ++ unused = write(2, "\n", 1); ++ _exit(EXIT_FAILURE); ++ } ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ __libc_init_tls(args); ++#endif ++ ++ // Initialize the linker's own global variables ++ linker_so.call_constructors(); ++ ++ // Initialize static variables. Note that in order to ++ // get correct libdl_info we need to call constructors ++ // before get_libdl_info(). ++ solist = get_libdl_info(); ++ sonext = get_libdl_info(); ++ ++ // We have successfully fixed our own relocations. It's safe to run ++ // the main part of the linker now. ++ args.abort_message_ptr = &g_abort_message; ++ ElfW(Addr) start_address = __linker_init_post_relocation(args, linker_addr); ++ ++ INFO("[ jumping to _start ]"); ++ ++ // Return the address that the calling assembly stub should jump to. ++ return start_address; ++} ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker.h +@@ -0,0 +1,441 @@ ++/* ++ * 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 _LINKER_H_ ++#define _LINKER_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "private/libc_logging.h" ++#include "linked_list.h" ++ ++#include ++#include ++ ++#define DL_ERR(fmt, x...) \ ++ do { \ ++ fprintf(stderr, fmt, ##x); \ ++ fprintf(stderr, "\n"); \ ++ /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \ ++ DEBUG("%s\n", linker_get_error_buffer()); \ ++ } while (false) ++ ++#define DL_WARN(fmt, x...) \ ++ do { \ ++ fprintf(stderr, "WARNING: linker " fmt, ##x); \ ++ fprintf(stderr, "\n"); \ ++ } while (false) ++ ++#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 ++ ++// 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)) ++ ++#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_NEW_SOINFO 0x40000000 // new soinfo format ++ ++#define SUPPORTED_DT_FLAGS_1 (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE) ++ ++#define SOINFO_VERSION 2 ++ ++#if defined(__work_around_b_19059885__) ++#define SOINFO_NAME_LEN 128 ++#endif ++ ++typedef void (*linker_function_t)(); ++ ++// 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* alloc(); ++ static void free(LinkedListEntry* entry); ++ ++ private: ++ // unconstructable ++ DISALLOW_IMPLICIT_CONSTRUCTORS(SoinfoListAllocator); ++}; ++ ++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 { ++ version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {} ++ ++ uint32_t elf_hash; ++ const char* name; ++ const soinfo* target_si; ++}; ++ ++// 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_infos; ++ ++ DISALLOW_COPY_AND_ASSIGN(VersionTracker); ++}; ++ ++struct soinfo { ++ public: ++ typedef LinkedList soinfo_list_t; ++#if defined(__work_around_b_19059885__) ++ private: ++ char old_name_[SOINFO_NAME_LEN]; ++#endif ++ public: ++ const ElfW(Phdr)* phdr; ++ size_t phnum; ++ ElfW(Addr) entry; ++ ElfW(Addr) base; ++ size_t size; ++ ++#if defined(__work_around_b_19059885__) ++ uint32_t unused1; // DO NOT USE, maintained for compatibility. ++#endif ++ ++ ElfW(Dyn)* dynamic; ++ ++#if defined(__work_around_b_19059885__) ++ 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_function_t* preinit_array_; ++ size_t preinit_array_count_; ++ ++ linker_function_t* init_array_; ++ size_t init_array_count_; ++ linker_function_t* fini_array_; ++ size_t fini_array_count_; ++ ++ linker_function_t init_func_; ++ linker_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); ++ ++#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(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags); ++ ++ 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); ++ ++ 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) const { ++#if defined(__work_around_b_19059885__) ++ (void) min_version; ++ return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version; ++#else ++ return true; ++#endif ++ } ++ ++ bool is_linked() const; ++ bool is_main_executable() const; ++ ++ void set_linked(); ++ void set_linker_flag(); ++ void set_main_executable(); ++ ++ void increment_ref_count(); ++ size_t decrement_ref_count(); ++ ++ soinfo* get_local_group_root() const; ++ ++ 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; ++ ++ bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const; ++ ++ uint32_t get_target_sdk_version() const; ++ ++ private: ++ 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); ++ ++ void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse); ++ void call_function(const char* function_name, linker_function_t function); ++ template ++ bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator, ++ const soinfo_list_t& global_group, const soinfo_list_t& local_group); ++ ++ 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_; ++ ++ uint32_t target_sdk_version_; ++ ++ friend soinfo* get_libdl_info(); ++}; ++ ++bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi, ++ soinfo** si_found_in, const soinfo::soinfo_list_t& global_group, ++ const soinfo::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(); ++ ++void do_android_get_LD_LIBRARY_PATH(char*, size_t); ++void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path); ++soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo); ++void do_dlclose(soinfo* si); ++ ++int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data); ++ ++const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle); ++soinfo* find_containing_library(const void* addr); ++ ++const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name); ++ ++void debuggerd_init(); ++extern "C" abort_msg_t* g_abort_message; ++extern "C" void notify_gdb_of_libraries(); ++ ++char* linker_get_error_buffer(); ++size_t linker_get_error_buffer_size(); ++ ++void set_application_target_sdk_version(uint32_t target); ++uint32_t get_application_target_sdk_version(); ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_allocator.cpp +@@ -0,0 +1,350 @@ ++/* ++ * 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. ++ */ ++ ++#include "linker_allocator.h" ++#include "linker.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#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() ++ : type_(0), name_(nullptr), block_size_(0), free_pages_cnt_(0), free_blocks_list_(nullptr) {} ++ ++void* LinkerSmallObjectAllocator::alloc() { ++ 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( ++ reinterpret_cast(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(page_record->page_addr); ++ void* page_end = reinterpret_cast(reinterpret_cast(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(ptr) - sizeof(page_info); ++ ++ if (offset % block_size_ != 0) { ++ __libc_fatal("invalid pointer: %p (block_size=%zd)", ptr, block_size_); ++ } ++ ++ memset(ptr, 0, block_size_); ++ small_object_block_record* block_record = reinterpret_cast(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); ++ } ++ } ++} ++ ++void LinkerSmallObjectAllocator::init(uint32_t type, size_t block_size, const char* name) { ++ type_ = type; ++ block_size_ = block_size; ++ name_ = name; ++} ++ ++linker_vector_t::iterator LinkerSmallObjectAllocator::find_page_record(void* ptr) { ++ void* addr = reinterpret_cast(PAGE_START(reinterpret_cast(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... ++ __libc_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() { ++ void* map_ptr = mmap(nullptr, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); ++ if (map_ptr == MAP_FAILED) { ++ __libc_fatal("mmap failed"); ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, name_); ++ ++ memset(map_ptr, 0, PAGE_SIZE); ++ ++ page_info* info = reinterpret_cast(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(info + 1); ++ ++ first_block->next = free_blocks_list_; ++ first_block->free_blocks_cnt = free_blocks_cnt; ++ ++ free_blocks_list_ = first_block; ++} ++ ++ ++LinkerMemoryAllocator::LinkerMemoryAllocator() { ++ static const char* allocator_names[kSmallObjectAllocatorsCount] = { ++ "linker_alloc_16", // 2^4 ++ "linker_alloc_32", // 2^5 ++ "linker_alloc_64", // and so on... ++ "linker_alloc_128", ++ "linker_alloc_256", ++ "linker_alloc_512", ++ "linker_alloc_1024", // 2^10 ++ }; ++ ++ for (size_t i = 0; i < kSmallObjectAllocatorsCount; ++i) { ++ uint32_t type = i + kSmallObjectMinSizeLog2; ++ allocators_[i].init(type, 1 << type, allocator_names[i]); ++ } ++} ++ ++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) { ++ __libc_fatal("mmap failed"); ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob"); ++ ++ memset(map_ptr, 0, allocated_size); ++ ++ page_info* info = reinterpret_cast(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_START(reinterpret_cast(ptr))); ++ if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) { ++ __libc_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) { ++ __libc_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) { ++ __libc_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) { ++ __libc_fatal("invalid type: %u", type); ++ } ++ ++ return &allocators_[type - kSmallObjectMinSizeLog2]; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_allocator.h +@@ -0,0 +1,143 @@ ++/* ++ * 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 __LINKER_ALLOCATOR_H ++#define __LINKER_ALLOCATOR_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "private/bionic_prctl.h" ++#include "private/libc_logging.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; ++ }; ++}; ++ ++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 ++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(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. ++ __libc_fatal("mmap failed"); ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "linker_alloc_vector"); ++ ++ return reinterpret_cast(ptr); ++ } ++ ++ void deallocate(T* ptr, size_t n) { ++ munmap(ptr, n * sizeof(T)); ++ } ++}; ++ ++typedef ++ std::vector> ++ linker_vector_t; ++ ++ ++class LinkerSmallObjectAllocator { ++ public: ++ LinkerSmallObjectAllocator(); ++ void init(uint32_t type, size_t block_size, const char* name); ++ 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_; ++ const char* name_; ++ 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: ++ LinkerMemoryAllocator(); ++ 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); ++ ++ LinkerSmallObjectAllocator allocators_[kSmallObjectAllocatorsCount]; ++}; ++ ++ ++#endif /* __LINKER_ALLOCATOR_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_block_allocator.cpp +@@ -0,0 +1,137 @@ ++/* ++ * 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. ++ */ ++ ++#include "linker_block_allocator.h" ++#include ++#include ++#include ++#include ++ ++#include "private/bionic_prctl.h" ++ ++#include "hybris_compat.h" ++ ++struct LinkerBlockAllocatorPage { ++ LinkerBlockAllocatorPage* next; ++ uint8_t bytes[PAGE_SIZE-sizeof(LinkerBlockAllocatorPage*)]; ++}; ++ ++struct FreeBlockInfo { ++ void* next_block; ++ size_t num_free_blocks; ++}; ++ ++LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size) ++ : block_size_(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size), ++ page_list_(nullptr), ++ free_block_list_(nullptr) ++{} ++ ++void* LinkerBlockAllocator::alloc() { ++ if (free_block_list_ == nullptr) { ++ create_new_page(); ++ } ++ ++ FreeBlockInfo* block_info = reinterpret_cast(free_block_list_); ++ if (block_info->num_free_blocks > 1) { ++ FreeBlockInfo* next_block_info = reinterpret_cast( ++ reinterpret_cast(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_); ++ ++ 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(block) - page->bytes; ++ ++ if (offset % block_size_ != 0) { ++ abort(); ++ } ++ ++ memset(block, 0, block_size_); ++ ++ FreeBlockInfo* block_info = reinterpret_cast(block); ++ ++ block_info->next_block = free_block_list_; ++ block_info->num_free_blocks = 1; ++ ++ free_block_list_ = block_info; ++} ++ ++void LinkerBlockAllocator::protect_all(int prot) { ++ for (LinkerBlockAllocatorPage* page = page_list_; page != nullptr; page = page->next) { ++ if (mprotect(page, PAGE_SIZE, prot) == -1) { ++ abort(); ++ } ++ } ++} ++ ++void LinkerBlockAllocator::create_new_page() { ++ LinkerBlockAllocatorPage* page = reinterpret_cast( ++ mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)); ++ ++ if (page == MAP_FAILED) { ++ abort(); // oom ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, PAGE_SIZE, "linker_alloc"); ++ ++ memset(page, 0, PAGE_SIZE); ++ ++ FreeBlockInfo* first_block = reinterpret_cast(page->bytes); ++ first_block->next_block = free_block_list_; ++ first_block->num_free_blocks = (PAGE_SIZE - sizeof(LinkerBlockAllocatorPage*))/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(page); ++ if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + PAGE_SIZE)) { ++ return page; ++ } ++ ++ page = page->next; ++ } ++ ++ abort(); ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_block_allocator.h +@@ -0,0 +1,81 @@ ++/* ++ * 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 __LINKER_BLOCK_ALLOCATOR_H ++#define __LINKER_BLOCK_ALLOCATOR_H ++ ++#include ++#include ++#include "private/bionic_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 where possible (everywhere). ++ */ ++class LinkerBlockAllocator { ++ public: ++ explicit LinkerBlockAllocator(size_t block_size); ++ ++ void* alloc(); ++ void free(void* block); ++ void protect_all(int prot); ++ ++ private: ++ void create_new_page(); ++ LinkerBlockAllocatorPage* find_page(void* block); ++ ++ size_t block_size_; ++ LinkerBlockAllocatorPage* page_list_; ++ void* free_block_list_; ++ ++ 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 LinkerMemoryAllocator are: ++ * 1. This allocator manages space more efficiently. LinkerMemoryAllocator ++ * 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 LinkerMemoryAllocator does. ++ * ++ * 3. This allocator provides mprotect services to the user, where LinkerMemoryAllocator ++ * always treats it's memory as READ|WRITE. ++ */ ++template ++class LinkerTypeAllocator { ++ public: ++ LinkerTypeAllocator() : block_allocator_(sizeof(T)) {} ++ T* alloc() { return reinterpret_cast(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); ++}; ++ ++#endif // __LINKER_BLOCK_ALLOCATOR_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_debug.h +@@ -0,0 +1,97 @@ ++/* ++ * 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 _LINKER_DEBUG_H_ ++#define _LINKER_DEBUG_H_ ++ ++// 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 0 ++ ++#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 "private/libc_logging.h" ++ ++extern int g_ld_debug_verbosity; ++ ++#define _PRINTVF(v, x...) \ ++ do { \ ++ if (g_ld_debug_verbosity > (v)) { fprintf(stderr, x); fprintf(stderr, "\n"); } \ ++ } while (0) ++ ++#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 ++ ++#endif /* _LINKER_DEBUG_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_libc_support.c +@@ -0,0 +1,21 @@ ++/* ++ * 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. ++ */ ++ ++#include "../libc/arch-common/bionic/__dso_handle.h" ++ ++int atexit(void (*function)(void) __attribute__((__unused__))) { ++ return -1; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_memory.cpp +@@ -0,0 +1,40 @@ ++/* ++ * 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. ++ */ ++ ++#include "linker_allocator.h" ++ ++#include ++ ++#if DISABLED_FOR_HYBRIS_SUPPORT ++static LinkerMemoryAllocator g_linker_allocator; ++ ++void* malloc(size_t byte_count) { ++ return g_linker_allocator.alloc(byte_count); ++} ++ ++void* calloc(size_t item_count, size_t item_size) { ++ return g_linker_allocator.alloc(item_count*item_size); ++} ++ ++void* realloc(void* p, size_t byte_count) { ++ return g_linker_allocator.realloc(p, byte_count); ++} ++ ++void free(void* ptr) { ++ g_linker_allocator.free(ptr); ++} ++#endif ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_phdr.cpp +@@ -0,0 +1,827 @@ ++/* ++ * 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 "linker_phdr.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "linker.h" ++#include "linker_debug.h" ++ ++#include "hybris_compat.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(const char* name, int fd, off64_t file_offset, off64_t file_size) ++ : name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size), ++ phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0), ++ load_start_(nullptr), load_size_(0), load_bias_(0), ++ loaded_phdr_(nullptr) { ++} ++ ++ElfReader::~ElfReader() { ++ if (phdr_mmap_ != nullptr) { ++ munmap(phdr_mmap_, phdr_size_); ++ } ++} ++ ++bool ElfReader::Load(const android_dlextinfo* extinfo) { ++ return ReadElfHeader() && ++ VerifyElfHeader() && ++ ReadProgramHeader() && ++ ReserveAddressSpace(extinfo) && ++ LoadSegments() && ++ FindPhdr(); ++} ++ ++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_, strerror(errno)); ++ return false; ++ } ++ ++ if (rc != sizeof(header_)) { ++ DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_, ++ static_cast(rc)); ++ return false; ++ } ++ return true; ++} ++ ++bool ElfReader::VerifyElfHeader() { ++ if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) { ++ DL_ERR("\"%s\" has bad ELF magic", name_); ++ 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_); ++ } else { ++ DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class); ++ } ++ return false; ++ } ++#else ++ if (elf_class != ELFCLASS32) { ++ if (elf_class == ELFCLASS64) { ++ DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_); ++ } else { ++ DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class); ++ } ++ return false; ++ } ++#endif ++ ++ if (header_.e_ident[EI_DATA] != ELFDATA2LSB) { ++ DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]); ++ return false; ++ } ++ ++ if (header_.e_type != ET_DYN) { ++ DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type); ++ return false; ++ } ++ ++ if (header_.e_version != EV_CURRENT) { ++ DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version); ++ return false; ++ } ++ ++ if (header_.e_machine != GetTargetElfMachine()) { ++ DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine); ++ return false; ++ } ++ ++ return true; ++} ++ ++// Loads the program header table from an ELF file into a read-only private ++// anonymous mmap-ed block. ++bool ElfReader::ReadProgramHeader() { ++ 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_, phdr_num_); ++ return false; ++ } ++ ++ ElfW(Addr) page_min = PAGE_START(header_.e_phoff); ++ ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr)))); ++ ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff); ++ ++ phdr_size_ = page_max - page_min; ++ ++ void* mmap_result = ++ mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min); ++ if (mmap_result == MAP_FAILED) { ++ DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno)); ++ return false; ++ } ++ ++ phdr_mmap_ = mmap_result; ++ phdr_table_ = reinterpret_cast(reinterpret_cast(mmap_result) + page_offset); ++ 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 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(const android_dlextinfo* extinfo) { ++ 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_); ++ return false; ++ } ++ ++ uint8_t* addr = reinterpret_cast(min_vaddr); ++ void* start; ++ size_t reserved_size = 0; ++ bool reserved_hint = true; ++ // Assume position independent executable by default. ++ uint8_t* mmap_hint = nullptr; ++ ++ if (extinfo != nullptr) { ++ if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) { ++ reserved_size = extinfo->reserved_size; ++ reserved_hint = false; ++ } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) { ++ reserved_size = extinfo->reserved_size; ++ } ++ ++ if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) { ++ mmap_hint = addr; ++ } ++ } ++ ++ if (load_size_ > reserved_size) { ++ if (!reserved_hint) { ++ DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"", ++ reserved_size - load_size_, load_size_, name_); ++ return false; ++ } ++ int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; ++ start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0); ++ if (start == MAP_FAILED) { ++ DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_); ++ return false; ++ } ++ } else { ++ start = extinfo->reserved_addr; ++ } ++ ++ load_start_ = start; ++ load_bias_ = reinterpret_cast(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_, file_size_); ++ return false; ++ } ++ ++ if (file_end >= static_cast(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_, i, reinterpret_cast(phdr->p_offset), ++ reinterpret_cast(phdr->p_filesz), ++ reinterpret_cast(file_end), file_size_); ++ return false; ++ } ++ ++ if (file_length != 0) { ++ void* seg_addr = mmap64(reinterpret_cast(seg_page_start), ++ file_length, ++ PFLAGS_TO_PROT(phdr->p_flags), ++ 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_, 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(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) { ++ void* zeromap = mmap(reinterpret_cast(seg_file_end), ++ seg_page_end - seg_file_end, ++ 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_, strerror(errno)); ++ return false; ++ } ++ } ++ } ++ 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(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(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 ++ * 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) { ++ const ElfW(Phdr)* phdr = phdr_table; ++ const ElfW(Phdr)* phdr_limit = phdr + phdr_count; ++ ssize_t file_offset = 0; ++ ++ 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(seg_page_start), size)); ++ if (written != size) { ++ return -1; ++ } ++ void* map = mmap(reinterpret_cast(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 ++ * 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) { ++ // 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; ++ } ++ } ++ size_t file_offset = 0; ++ ++ // 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(temp_mapping) + file_offset; ++ char* mem_base = reinterpret_cast(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, 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(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(load_bias + phdr.p_vaddr); ++ if (dynamic_flags) { ++ *dynamic_flags = phdr.p_flags; ++ } ++ return; ++ } ++ } ++} ++ ++// 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(elf_addr); ++ ElfW(Addr) offset = ehdr->e_phoff; ++ return CheckPhdr(reinterpret_cast(ehdr) + offset); ++ } ++ break; ++ } ++ } ++ ++ DL_ERR("can't find loaded phdr for \"%s\"", name_); ++ 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 (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(loaded); ++ return true; ++ } ++ } ++ DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast(loaded)); ++ return false; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_phdr.h +@@ -0,0 +1,112 @@ ++/* ++ * 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 LINKER_PHDR_H ++#define LINKER_PHDR_H ++ ++/* 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" ++ ++class ElfReader { ++ public: ++ ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size); ++ ~ElfReader(); ++ ++ bool Load(const android_dlextinfo* extinfo); ++ ++ size_t phdr_count() { return phdr_num_; } ++ ElfW(Addr) load_start() { return reinterpret_cast(load_start_); } ++ size_t load_size() { return load_size_; } ++ ElfW(Addr) load_bias() { return load_bias_; } ++ const ElfW(Phdr)* loaded_phdr() { return loaded_phdr_; } ++ ++ private: ++ bool ReadElfHeader(); ++ bool VerifyElfHeader(); ++ bool ReadProgramHeader(); ++ bool ReserveAddressSpace(const android_dlextinfo* extinfo); ++ bool LoadSegments(); ++ bool FindPhdr(); ++ bool CheckPhdr(ElfW(Addr)); ++ ++ const char* name_; ++ int fd_; ++ off64_t file_offset_; ++ off64_t file_size_; ++ ++ ElfW(Ehdr) header_; ++ size_t phdr_num_; ++ ++ void* phdr_mmap_; ++ ElfW(Phdr)* phdr_table_; ++ ElfW(Addr) phdr_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_; ++}; ++ ++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); ++ ++int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, int fd); ++ ++#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); ++ ++#endif /* LINKER_PHDR_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_reloc_iterators.h +@@ -0,0 +1,165 @@ ++/* ++ * 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 __LINKER_RELOC_ITERATORS_H ++#define __LINKER_RELOC_ITERATORS_H ++ ++#include "linker.h" ++ ++#include ++ ++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 ++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_; ++}; ++ ++#endif // __LINKER_RELOC_ITERATORS_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_relocs.h +@@ -0,0 +1,54 @@ ++/* ++ * 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 __LINKER_RELOCS_H ++#define __LINKER_RELOCS_H ++ ++#include ++ ++#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 ++ ++#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 ++ ++#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 ++ ++#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 ++ ++#endif ++ ++#endif // __LINKER_RELOCS_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_sdk_versions.cpp +@@ -0,0 +1,34 @@ ++/* ++ * 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. ++ */ ++ ++#include "linker.h" ++#include ++#include ++ ++static std::atomic g_target_sdk_version(__ANDROID_API__); ++ ++void set_application_target_sdk_version(uint32_t target) { ++ // translate current sdk_version to platform sdk_version ++ if (target == 0) { ++ target = __ANDROID_API__; ++ } ++ g_target_sdk_version = target; ++} ++ ++uint32_t get_application_target_sdk_version() { ++ return g_target_sdk_version; ++} ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_sleb128.h +@@ -0,0 +1,58 @@ ++/* ++ * 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 _LINKER_SLEB128_H ++#define _LINKER_SLEB128_H ++ ++#include ++ ++// 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_) { ++ __libc_fatal("sleb128_decoder ran out of bounds"); ++ } ++ byte = *current_++; ++ value |= (static_cast(byte & 127) << shift); ++ shift += 7; ++ } while (byte & 128); ++ ++ if (shift < size && (byte & 64)) { ++ value |= -(static_cast(1) << shift); ++ } ++ ++ return value; ++ } ++ ++ private: ++ const uint8_t* current_; ++ const uint8_t* const end_; ++}; ++ ++#endif // __LINKER_SLEB128_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/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() { ++} ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/strlcat.c +@@ -0,0 +1,59 @@ ++/* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */ ++ ++/* ++ * Copyright (c) 1998 Todd C. Miller ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#if defined(LIBC_SCCS) && !defined(lint) ++static char *rcsid = "$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $"; ++#endif /* LIBC_SCCS and not lint */ ++ ++#include ++#include ++ ++/* ++ * Appends src to string dst of size siz (unlike strncat, siz is the ++ * full size of dst, not space left). At most siz-1 characters ++ * will be copied. Always NUL terminates (unless siz <= strlen(dst)). ++ * Returns strlen(src) + MIN(siz, strlen(initial dst)). ++ * If retval >= siz, truncation occurred. ++ */ ++size_t ++strlcat(char *dst, const char *src, size_t siz) ++{ ++ register char *d = dst; ++ register const char *s = src; ++ register size_t n = siz; ++ size_t dlen; ++ ++ /* Find the end of dst and adjust bytes left but don't go past end */ ++ while (n-- != 0 && *d != '\0') ++ d++; ++ dlen = d - dst; ++ n = siz - dlen; ++ ++ if (n == 0) ++ return(dlen + strlen(s)); ++ while (*s != '\0') { ++ if (n != 1) { ++ *d++ = *s; ++ n--; ++ } ++ s++; ++ } ++ *d = '\0'; ++ ++ return(dlen + (s - src)); /* count does not include NUL */ ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/stub/Makefile.am +@@ -0,0 +1,4 @@ ++noinst_LTLIBRARIES = \ ++ libstub-linker.la ++libstub_linker_la_SOURCES = \ ++ linker.c +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/stub/linker.c +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (c) 2016 Canonical Ltd ++ * ++ * 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 ++#include ++ ++void *android_dlopen(const char *filename, int flag) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return NULL; ++} ++ ++void *android_dlsym(void *name, const char *symbol) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return NULL; ++} ++ ++int android_dlclose(void *handle) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return -1; ++} ++ ++const char *android_dlerror(void) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return NULL; ++} ++ ++int android_dladdr(const void *addr, void *info) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return -1; ++} +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/sysconf.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/sysconf.c +@@ -1,8 +1,27 @@ ++/* ++ * Copyright (c) 2013 Adrian Negreanu ++ * ++ * 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 + + /* +- * bionic/libc/include/sys/sysconf.h processed with s/define _\(\w*\)\(.*\)/define \1\2\r#ifdef _\1\rMAP_TO_UNISTD(\1),\r#endif/g ++ * bionic/libc/include/sys/sysconf.h processed with: ++ * s/define _\(\w*\)\(.*\)/define \1\2\r#ifdef _\1\rMAP_TO_UNISTD(\1),\r#endif/g + */ ++ + #define MAP_TO_UNISTD(a) [a]=_##a + static int sysconf_map[]= { + #define SC_ARG_MAX 0x0000 +@@ -321,7 +340,6 @@ MAP_TO_UNISTD(SC_THREAD_THREADS_MAX), + #ifdef _SC_TTY_NAME_MAX + MAP_TO_UNISTD(SC_TTY_NAME_MAX), + #endif +- + #define SC_THREADS 0x004f + #ifdef _SC_THREADS + MAP_TO_UNISTD(SC_THREADS), +@@ -350,7 +368,6 @@ MAP_TO_UNISTD(SC_THREAD_PRIO_PROTECT), + #ifdef _SC_THREAD_SAFE_FUNCTIONS + MAP_TO_UNISTD(SC_THREAD_SAFE_FUNCTIONS), + #endif +- + #define SC_NPROCESSORS_CONF 0x0060 + #ifdef _SC_NPROCESSORS_CONF + MAP_TO_UNISTD(SC_NPROCESSORS_CONF), +@@ -367,10 +384,242 @@ MAP_TO_UNISTD(SC_PHYS_PAGES), + #ifdef _SC_AVPHYS_PAGES + MAP_TO_UNISTD(SC_AVPHYS_PAGES), + #endif ++#define SC_MONOTONIC_CLOCK 0x0064 ++#ifdef _SC_MONOTONIC_CLOCK ++MAP_TO_UNISTD(SC_MONOTONIC_CLOCK), ++#endif ++#define SC_2_PBS 0x0065 ++#ifdef _SC_2_PBS ++MAP_TO_UNISTD(SC_2_PBS), ++#endif ++#define SC_2_PBS_ACCOUNTING 0x0066 ++#ifdef _SC_2_PBS_ACCOUNTING ++MAP_TO_UNISTD(SC_2_PBS_ACCOUNTING), ++#endif ++#define SC_2_PBS_CHECKPOINT 0x0067 ++#ifdef _SC_2_PBS_CHECKPOINT ++MAP_TO_UNISTD(SC_2_PBS_CHECKPOINT), ++#endif ++#define SC_2_PBS_LOCATE 0x0068 ++#ifdef _SC_2_PBS_LOCATE ++MAP_TO_UNISTD(SC_2_PBS_LOCATE), ++#endif ++#define SC_2_PBS_MESSAGE 0x0069 ++#ifdef _SC_2_PBS_MESSAGE ++MAP_TO_UNISTD(SC_2_PBS_MESSAGE), ++#endif ++#define SC_2_PBS_TRACK 0x006a ++#ifdef _SC_2_PBS_TRACK ++MAP_TO_UNISTD(SC_2_PBS_TRACK), ++#endif ++#define SC_ADVISORY_INFO 0x006b ++#ifdef _SC_ADVISORY_INFO ++MAP_TO_UNISTD(SC_ADVISORY_INFO), ++#endif ++#define SC_BARRIERS 0x006c ++#ifdef _SC_BARRIERS ++MAP_TO_UNISTD(SC_BARRIERS), ++#endif ++#define SC_CLOCK_SELECTION 0x006d ++#ifdef _SC_CLOCK_SELECTION ++MAP_TO_UNISTD(SC_CLOCK_SELECTION), ++#endif ++#define SC_CPUTIME 0x006e ++#ifdef _SC_CPUTIME ++MAP_TO_UNISTD(SC_CPUTIME), ++#endif ++#define SC_HOST_NAME_MAX 0x006f ++#ifdef _SC_HOST_NAME_MAX ++MAP_TO_UNISTD(SC_HOST_NAME_MAX), ++#endif ++#define SC_IPV6 0x0070 ++#ifdef _SC_IPV6 ++MAP_TO_UNISTD(SC_IPV6), ++#endif ++#define SC_RAW_SOCKETS 0x0071 ++#ifdef _SC_RAW_SOCKETS ++MAP_TO_UNISTD(SC_RAW_SOCKETS), ++#endif ++#define SC_READER_WRITER_LOCKS 0x0072 ++#ifdef _SC_READER_WRITER_LOCKS ++MAP_TO_UNISTD(SC_READER_WRITER_LOCKS), ++#endif ++#define SC_REGEXP 0x0073 ++#ifdef _SC_REGEXP ++MAP_TO_UNISTD(SC_REGEXP), ++#endif ++#define SC_SHELL 0x0074 ++#ifdef _SC_SHELL ++MAP_TO_UNISTD(SC_SHELL), ++#endif ++#define SC_SPAWN 0x0075 ++#ifdef _SC_SPAWN ++MAP_TO_UNISTD(SC_SPAWN), ++#endif ++#define SC_SPIN_LOCKS 0x0076 ++#ifdef _SC_SPIN_LOCKS ++MAP_TO_UNISTD(SC_SPIN_LOCKS), ++#endif ++#define SC_SPORADIC_SERVER 0x0077 ++#ifdef _SC_SPORADIC_SERVER ++MAP_TO_UNISTD(SC_SPORADIC_SERVER), ++#endif ++#define SC_SS_REPL_MAX 0x0078 ++#ifdef _SC_SS_REPL_MAX ++MAP_TO_UNISTD(SC_SS_REPL_MAX), ++#endif ++#define SC_SYMLOOP_MAX 0x0079 ++#ifdef _SC_SYMLOOP_MAX ++MAP_TO_UNISTD(SC_SYMLOOP_MAX), ++#endif ++#define SC_THREAD_CPUTIME 0x007a ++#ifdef _SC_THREAD_CPUTIME ++MAP_TO_UNISTD(SC_THREAD_CPUTIME), ++#endif ++#define SC_THREAD_PROCESS_SHARED 0x007b ++#ifdef _SC_THREAD_PROCESS_SHARED ++MAP_TO_UNISTD(SC_THREAD_PROCESS_SHARED), ++#endif ++#define SC_THREAD_ROBUST_PRIO_INHERIT 0x007c ++#ifdef _SC_THREAD_ROBUST_PRIO_INHERIT ++MAP_TO_UNISTD(SC_THREAD_ROBUST_PRIO_INHERIT), ++#endif ++#define SC_THREAD_ROBUST_PRIO_PROTECT 0x007d ++#ifdef _SC_THREAD_ROBUST_PRIO_PROTECT ++MAP_TO_UNISTD(SC_THREAD_ROBUST_PRIO_PROTECT), ++#endif ++#define SC_THREAD_SPORADIC_SERVER 0x007e ++#ifdef _SC_THREAD_SPORADIC_SERVER ++MAP_TO_UNISTD(SC_THREAD_SPORADIC_SERVER), ++#endif ++#define SC_TIMEOUTS 0x007f ++#ifdef _SC_TIMEOUTS ++MAP_TO_UNISTD(SC_TIMEOUTS), ++#endif ++#define SC_TRACE 0x0080 ++#ifdef _SC_TRACE ++MAP_TO_UNISTD(SC_TRACE), ++#endif ++#define SC_TRACE_EVENT_FILTER 0x0081 ++#ifdef _SC_TRACE_EVENT_FILTER ++MAP_TO_UNISTD(SC_TRACE_EVENT_FILTER), ++#endif ++#define SC_TRACE_EVENT_NAME_MAX 0x0082 ++#ifdef _SC_TRACE_EVENT_NAME_MAX ++MAP_TO_UNISTD(SC_TRACE_EVENT_NAME_MAX), ++#endif ++#define SC_TRACE_INHERIT 0x0083 ++#ifdef _SC_TRACE_INHERIT ++MAP_TO_UNISTD(SC_TRACE_INHERIT), ++#endif ++#define SC_TRACE_LOG 0x0084 ++#ifdef _SC_TRACE_LOG ++MAP_TO_UNISTD(SC_TRACE_LOG), ++#endif ++#define SC_TRACE_NAME_MAX 0x0085 ++#ifdef _SC_TRACE_NAME_MAX ++MAP_TO_UNISTD(SC_TRACE_NAME_MAX), ++#endif ++#define SC_TRACE_SYS_MAX 0x0086 ++#ifdef _SC_TRACE_SYS_MAX ++MAP_TO_UNISTD(SC_TRACE_SYS_MAX), ++#endif ++#define SC_TRACE_USER_EVENT_MAX 0x0087 ++#ifdef _SC_TRACE_USER_EVENT_MAX ++MAP_TO_UNISTD(SC_TRACE_USER_EVENT_MAX), ++#endif ++#define SC_TYPED_MEMORY_OBJECTS 0x0088 ++#ifdef _SC_TYPED_MEMORY_OBJECTS ++MAP_TO_UNISTD(SC_TYPED_MEMORY_OBJECTS), ++#endif ++#define SC_V7_ILP32_OFF32 0x0089 ++#ifdef _SC_V7_ILP32_OFF32 ++MAP_TO_UNISTD(SC_V7_ILP32_OFF32), ++#endif ++#define SC_V7_ILP32_OFFBIG 0x008a ++#ifdef _SC_V7_ILP32_OFFBIG ++MAP_TO_UNISTD(SC_V7_ILP32_OFFBIG), ++#endif ++#define SC_V7_LP64_OFF64 0x008b ++#ifdef _SC_V7_LP64_OFF64 ++MAP_TO_UNISTD(SC_V7_LP64_OFF64), ++#endif ++#define SC_V7_LPBIG_OFFBIG 0x008c ++#ifdef _SC_V7_LPBIG_OFFBIG ++MAP_TO_UNISTD(SC_V7_LPBIG_OFFBIG), ++#endif ++#define SC_XOPEN_STREAMS 0x008d ++#ifdef _SC_XOPEN_STREAMS ++MAP_TO_UNISTD(SC_XOPEN_STREAMS), ++#endif ++#define SC_XOPEN_UUCP 0x008e ++#ifdef _SC_XOPEN_UUCP ++MAP_TO_UNISTD(SC_XOPEN_UUCP), ++#endif ++#define SC_LEVEL1_ICACHE_SIZE 0x008f ++#ifdef _SC_LEVEL1_ICACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL1_ICACHE_SIZE), ++#endif ++#define SC_LEVEL1_ICACHE_ASSOC 0x0090 ++#ifdef _SC_LEVEL1_ICACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL1_ICACHE_ASSOC), ++#endif ++#define SC_LEVEL1_ICACHE_LINESIZE 0x0091 ++#ifdef _SC_LEVEL1_ICACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL1_ICACHE_LINESIZE), ++#endif ++#define SC_LEVEL1_DCACHE_SIZE 0x0092 ++#ifdef _SC_LEVEL1_DCACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL1_DCACHE_SIZE), ++#endif ++#define SC_LEVEL1_DCACHE_ASSOC 0x0093 ++#ifdef _SC_LEVEL1_DCACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL1_DCACHE_ASSOC), ++#endif ++#define SC_LEVEL1_DCACHE_LINESIZE 0x0094 ++#ifdef _SC_LEVEL1_DCACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL1_DCACHE_LINESIZE), ++#endif ++#define SC_LEVEL2_CACHE_SIZE 0x0095 ++#ifdef _SC_LEVEL2_CACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL2_CACHE_SIZE), ++#endif ++#define SC_LEVEL2_CACHE_ASSOC 0x0096 ++#ifdef _SC_LEVEL2_CACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL2_CACHE_ASSOC), ++#endif ++#define SC_LEVEL2_CACHE_LINESIZE 0x0097 ++#ifdef _SC_LEVEL2_CACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL2_CACHE_LINESIZE), ++#endif ++#define SC_LEVEL3_CACHE_SIZE 0x0098 ++#ifdef _SC_LEVEL3_CACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL3_CACHE_SIZE), ++#endif ++#define SC_LEVEL3_CACHE_ASSOC 0x0099 ++#ifdef _SC_LEVEL3_CACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL3_CACHE_ASSOC), ++#endif ++#define SC_LEVEL3_CACHE_LINESIZE 0x009a ++#ifdef _SC_LEVEL3_CACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL3_CACHE_LINESIZE), ++#endif ++#define SC_LEVEL4_CACHE_SIZE 0x009b ++#ifdef _SC_LEVEL4_CACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL4_CACHE_SIZE), ++#endif ++#define SC_LEVEL4_CACHE_ASSOC 0x009c ++#ifdef _SC_LEVEL4_CACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL4_CACHE_ASSOC), ++#endif ++#define SC_LEVEL4_CACHE_LINESIZE 0x009d ++#ifdef _SC_LEVEL4_CACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL4_CACHE_LINESIZE), ++#endif + }; + #undef MAP_TO_UNISTD + +-long my_sysconf(int name) ++long _hybris_map_sysconf(int name) + { + return sysconf(sysconf_map[name]); + } +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/configure.ac ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/configure.ac +@@ -42,6 +42,12 @@ AC_ARG_ENABLE(debug, + [debug="no"]) + AM_CONDITIONAL( [WANT_DEBUG], [test x"$debug" = x"yes"]) + ++AC_ARG_ENABLE(experimental, ++ [ --enable-experimental Enable experimental features (default=disabled)], ++ [experimental=$enableval], ++ [experimental="no"]) ++AM_CONDITIONAL( [WANT_EXPERIMENTAL], [test x"$experimental" = x"yes"]) ++ + AC_ARG_ENABLE(trace, + [ --enable-trace Enable TRACE statements (default=disabled)], + [trace=$enableval], +@@ -73,14 +79,30 @@ AC_ARG_ENABLE(wayland_serverside_buffers + [wayland_serverside_buffers=yes]) + AM_CONDITIONAL( [WANT_WL_SERVERSIDE_BUFFERS], [test x"$wayland_serverside_buffers" = x"yes"]) + ++AC_ARG_ENABLE(property_cache, ++ [ --enable-property-cache Enable runtime android property cache (default=disabled)], ++ [property_cache=$enableval], ++ [property_cache=no]) ++AM_CONDITIONAL( [WANT_RUNTIME_PROPERTY_CACHE], [test x"$property_cache" = x"yes"]) ++ ++AC_ARG_ENABLE(ubuntu-linker-overrides, ++ [ --enable-ubuntu-linker-overrides Enable Ubuntu linker overrides (default=disabled)], ++ [ubuntu_linker_overrides=$enableval], ++ [ubuntu_linker_overrides=no]) ++AM_CONDITIONAL([WANT_UBUNTU_LINKER_OVERRIDES], [test x"$ubuntu_linker_overrides" = x"yes"]) ++ + AC_ARG_ENABLE(arch, + [ --enable-arch[=arch] Compile specific CPU target(default=arm) + arm: compile for ARM + x86: Compile for x86], + [ if test "x$enableval" = "xarm" ; then + arch="arm" ++ elif test "x$enableval" = "xarm64" ; then ++ arch="arm64" + elif test "x$enableval" = "xx86" ; then + arch="x86" ++ elif test "x$enableval" = "xx86-64" ; then ++ arch="x86-64" + else + echo + echo "Error!" +@@ -91,7 +113,9 @@ AC_ARG_ENABLE(arch, + [arch="arm"] + ) + AM_CONDITIONAL([WANT_ARCH_ARM], [test x$arch = xarm]) ++AM_CONDITIONAL([WANT_ARCH_ARM64], [test x$arch = xarm64]) + AM_CONDITIONAL([WANT_ARCH_X86], [test x$arch = xx86]) ++AM_CONDITIONAL([WANT_ARCH_X86_64], [test x$arch = xx86-64]) + + DEFAULT_EGL_PLATFORM="null" + AC_ARG_WITH(default-egl-platform, +@@ -100,7 +124,11 @@ AC_ARG_WITH(default-egl-platform, + [ ]) + AC_SUBST(DEFAULT_EGL_PLATFORM) + +-DEFAULT_HYBRIS_LD_LIBRARY_PATH="/vendor/lib:/system/lib" ++if test "x$arch" = "xarm" -o "x$arch" = "xx86"; then ++ DEFAULT_HYBRIS_LD_LIBRARY_PATH="/vendor/lib:/system/lib" ++else ++ DEFAULT_HYBRIS_LD_LIBRARY_PATH="/vendor/lib64:/system/lib64" ++fi + AC_ARG_WITH(default-hybris-ld-library-path, + [ --with-default-hybris-ld-library-path=PATH1:PATH2:... Use PATH1:PATH2 for default HYBRIS_LD_LIBRARY_PATH if not specified by environment ], + [ DEFAULT_HYBRIS_LD_LIBRARY_PATH="$withval" ], +@@ -114,7 +142,10 @@ AC_ARG_WITH(android-headers, + AS_IF([test -f $withval/libnfc-nxp/phLibNfc.h], [ANDROID_HEADERS_CFLAGS="-I$withval -I$withval/libnfc-nxp"],[ANDROID_HEADERS_CFLAGS="-I$withval"]) + AC_SUBST([ANDROID_HEADERS_CFLAGS]) + ], +- [ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) ] ++ [ ++ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) ++ AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [false]) ++ ] + ) + CPPFLAGS="$CPPFLAGS $ANDROID_HEADERS_CFLAGS" + +@@ -177,15 +208,26 @@ AM_CONDITIONAL([HAS_ANDROID_4_1_0], [tes + AM_CONDITIONAL([HAS_ANDROID_4_0_0], [test $android_headers_major -ge 4 -a $android_headers_minor -ge 0 ]) + AM_CONDITIONAL([HAS_ANDROID_2_3_0], [test $android_headers_major -ge 2 -a $android_headers_minor -ge 3 ]) + ++AC_ARG_ENABLE(mali-quirks, ++ [ --enable-mali-quirks Enable Mali GPU driver quirks (default=disabled)], ++ [mali_quirks=$enableval], ++ [mali_quirks="no"]) ++AM_CONDITIONAL([WANT_MALI_QUIRKS], [test x"$mali_quirks" = x"yes"]) ++ ++AC_ARG_ENABLE(stub-linker, ++ [ --enable-stub-linker Enable a stub linker which does nothing (default=disabled)], ++ [stub_linker=$enableval], ++ [stub_linker="no"]) ++AM_CONDITIONAL([WANT_STUB_LINKER], [test x"$stub_linker" = x"yes"]) + + AC_CONFIG_FILES([ + Makefile + properties/Makefile + properties/libandroid-properties.pc + common/Makefile +- common/gingerbread/Makefile +- common/ics/Makefile + common/jb/Makefile ++ common/stub/Makefile ++ common/mm/Makefile + egl/egl.pc + egl/Makefile + egl/platforms/Makefile +@@ -217,6 +259,10 @@ AC_CONFIG_FILES([ + camera/libcamera.pc + vibrator/Makefile + vibrator/libvibrator.pc ++ media/Makefile ++ media/libmedia.pc ++ wifi/Makefile ++ wifi/libwifi.pc + include/Makefile + utils/Makefile + tests/Makefile +@@ -236,16 +282,26 @@ echo " debug build.............: $debug + echo + echo " trace...................: $trace" + echo ++echo " experimental features...: $experimental" ++echo + echo " prefix..................: $prefix" + echo + echo " arch ..................: $arch" + echo + echo " headers path ...........: $android_headers_path" + echo ++echo " Android version.........: $android_headers_major.$android_headers_minor.$android_headers_patch" ++echo + echo " default egl platform ...: $DEFAULT_EGL_PLATFORM" + echo + echo " default ld_library_path.: $DEFAULT_HYBRIS_LD_LIBRARY_PATH" + echo ++echo "Features:" ++echo ++echo " stub linker.............: $stub_linker" ++echo ++echo " Ubuntu linker overrides.: $ubuntu_linker_overrides" ++echo + echo "------------------------------------------------------------------------" + echo + echo "Now type 'make' to compile and 'make install' to install this package." +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/egl/egl.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/egl.c +@@ -266,8 +266,11 @@ EGLSurface eglCreateWindowSurface(EGLDis + + HYBRIS_TRACE_BEGIN("native-egl", "eglCreateWindowSurface", ""); + EGLSurface result = (*_eglCreateWindowSurface)(dpy, config, win, attrib_list); ++ + HYBRIS_TRACE_END("native-egl", "eglCreateWindowSurface", ""); +- egl_helper_push_mapping(result, win); ++ ++ if (result != EGL_NO_SURFACE) ++ egl_helper_push_mapping(result, win); + + HYBRIS_TRACE_END("hybris-egl", "eglCreateWindowSurface", ""); + return result; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/egl/platforms/null/eglplatform_null.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/null/eglplatform_null.c +@@ -16,7 +16,7 @@ static alloc_device_t *alloc = 0; + + static void _init_androidui() + { +- _libui = (void *) android_dlopen("/system/lib/libui.so", RTLD_LAZY); ++ _libui = (void *) android_dlopen("libui.so", RTLD_LAZY); + } + + #define UI_DLSYM(fptr, sym) do { if (_libui == NULL) { _init_androidui(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libui, sym); } } while (0) +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/glesv1/glesv1_cm.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv1/glesv1_cm.c +@@ -26,7 +26,7 @@ + + #include + +-#define GLESV1_CM_LIBRARY_PATH "/system/lib/libGLESv1_CM.so" ++#define GLESV1_CM_LIBRARY_PATH "libGLESv1_CM.so" + + HYBRIS_LIBRARY_INITIALIZE(glesv1_cm, GLESV1_CM_LIBRARY_PATH); + +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/glesv2/glesv2.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv2/glesv2.c +@@ -22,404 +22,1028 @@ + #include + #include + +-#include + #include +-#include + + static void *_libglesv2 = NULL; + +-/* Only functions with floating point argument need a wrapper to change the call convention correctly */ +- ++static void (*_glActiveTexture)(GLenum texture) = NULL; ++static void (*_glAttachShader)(GLuint program, GLuint shader) = NULL; ++static void (*_glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) = NULL; ++static void (*_glBindBuffer)(GLenum target, GLuint buffer) = NULL; ++static void (*_glBindFramebuffer)(GLenum target, GLuint framebuffer) = NULL; ++static void (*_glBindRenderbuffer)(GLenum target, GLuint renderbuffer) = NULL; ++static void (*_glBindTexture)(GLenum target, GLuint texture) = NULL; + static void (*_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) FP_ATTRIB = NULL; ++static void (*_glBlendEquation)(GLenum mode ) = NULL; ++static void (*_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) = NULL; ++static void (*_glBlendFunc)(GLenum sfactor, GLenum dfactor) = NULL; ++static void (*_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) = NULL; ++static void (*_glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) = NULL; ++static void (*_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) = NULL; ++static GLenum (*_glCheckFramebufferStatus)(GLenum target) = NULL; ++static void (*_glClear)(GLbitfield mask) = NULL; + static void (*_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) FP_ATTRIB = NULL; + static void (*_glClearDepthf)(GLclampf depth) FP_ATTRIB = NULL; ++static void (*_glClearStencil)(GLint s) = NULL; ++static void (*_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = NULL; ++static void (*_glCompileShader)(GLuint shader) = NULL; ++static void (*_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) = NULL; ++static void (*_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) = NULL; ++static void (*_glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = NULL; ++static void (*_glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; ++static GLuint (*_glCreateProgram)(void) = NULL; ++static GLuint (*_glCreateShader)(GLenum type) = NULL; ++static void (*_glCullFace)(GLenum mode) = NULL; ++static void (*_glDeleteBuffers)(GLsizei n, const GLuint* buffers) = NULL; ++static void (*_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) = NULL; ++static void (*_glDeleteProgram)(GLuint program) = NULL; ++static void (*_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) = NULL; ++static void (*_glDeleteShader)(GLuint shader) = NULL; ++static void (*_glDeleteTextures)(GLsizei n, const GLuint* textures) = NULL; ++static void (*_glDepthFunc)(GLenum func) = NULL; ++static void (*_glDepthMask)(GLboolean flag) = NULL; + static void (*_glDepthRangef)(GLclampf zNear, GLclampf zFar) FP_ATTRIB = NULL; ++static void (*_glDetachShader)(GLuint program, GLuint shader) = NULL; ++static void (*_glDisable)(GLenum cap) = NULL; ++static void (*_glDisableVertexAttribArray)(GLuint index) = NULL; ++static void (*_glDrawArrays)(GLenum mode, GLint first, GLsizei count) = NULL; ++static void (*_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) = NULL; ++static void (*_glEnable)(GLenum cap) = NULL; ++static void (*_glEnableVertexAttribArray)(GLuint index) = NULL; ++static void (*_glFinish)(void) = NULL; ++static void (*_glFlush)(void) = NULL; ++static void (*_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = NULL; ++static void (*_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = NULL; ++static void (*_glFrontFace)(GLenum mode) = NULL; ++static void (*_glGenBuffers)(GLsizei n, GLuint* buffers) = NULL; ++static void (*_glGenerateMipmap)(GLenum target) = NULL; ++static void (*_glGenFramebuffers)(GLsizei n, GLuint* framebuffers) = NULL; ++static void (*_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) = NULL; ++static void (*_glGenTextures)(GLsizei n, GLuint* textures) = NULL; ++static void (*_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; ++static void (*_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; ++static void (*_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) = NULL; ++static int (*_glGetAttribLocation)(GLuint program, const GLchar* name) = NULL; ++static void (*_glGetBooleanv)(GLenum pname, GLboolean* params) = NULL; ++static void (*_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; ++static GLenum (*_glGetError)(void) = NULL; ++static void (*_glGetFloatv)(GLenum pname, GLfloat* params) = NULL; ++static void (*_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) = NULL; ++static void (*_glGetIntegerv)(GLenum pname, GLint* params) = NULL; ++static void (*_glGetProgramiv)(GLuint program, GLenum pname, GLint* params) = NULL; ++static void (*_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; ++static void (*_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; ++static void (*_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) = NULL; ++static void (*_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; ++static void (*_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) = NULL; ++static void (*_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) = NULL; ++static const GLubyte* (*_glGetString)(GLenum name) = NULL; ++static void (*_glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) = NULL; ++static void (*_glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; ++static void (*_glGetUniformfv)(GLuint program, GLint location, GLfloat* params) = NULL; ++static void (*_glGetUniformiv)(GLuint program, GLint location, GLint* params) = NULL; ++static int (*_glGetUniformLocation)(GLuint program, const GLchar* name) = NULL; ++static void (*_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) = NULL; ++static void (*_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) = NULL; ++static void (*_glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) = NULL; ++static void (*_glHint)(GLenum target, GLenum mode) = NULL; ++static GLboolean (*_glIsBuffer)(GLuint buffer) = NULL; ++static GLboolean (*_glIsEnabled)(GLenum cap) = NULL; ++static GLboolean (*_glIsFramebuffer)(GLuint framebuffer) = NULL; ++static GLboolean (*_glIsProgram)(GLuint program) = NULL; ++static GLboolean (*_glIsRenderbuffer)(GLuint renderbuffer) = NULL; ++static GLboolean (*_glIsShader)(GLuint shader) = NULL; ++static GLboolean (*_glIsTexture)(GLuint texture) = NULL; + static void (*_glLineWidth)(GLfloat width) FP_ATTRIB = NULL; ++static void (*_glLinkProgram)(GLuint program) = NULL; ++static void (*_glPixelStorei)(GLenum pname, GLint param) = NULL; + static void (*_glPolygonOffset)(GLfloat factor, GLfloat units) FP_ATTRIB = NULL; ++static void (*_glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = NULL; ++static void (*_glReleaseShaderCompiler)(void) = NULL; ++static void (*_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = NULL; + static void (*_glSampleCoverage)(GLclampf value, GLboolean invert) FP_ATTRIB = NULL; ++static void (*_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; ++static void (*_glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) = NULL; ++static void (*_glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) = NULL; ++static void (*_glStencilFunc)(GLenum func, GLint ref, GLuint mask) = NULL; ++static void (*_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) = NULL; ++static void (*_glStencilMask)(GLuint mask) = NULL; ++static void (*_glStencilMaskSeparate)(GLenum face, GLuint mask) = NULL; ++static void (*_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) = NULL; ++static void (*_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) = NULL; ++static void (*_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) = NULL; + static void (*_glTexParameterf)(GLenum target, GLenum pname, GLfloat param) FP_ATTRIB = NULL; ++static void (*_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) = NULL; ++static void (*_glTexParameteri)(GLenum target, GLenum pname, GLint param) = NULL; ++static void (*_glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) = NULL; ++static void (*_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) = NULL; + static void (*_glUniform1f)(GLint location, GLfloat x) FP_ATTRIB = NULL; ++static void (*_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform1i)(GLint location, GLint x) = NULL; ++static void (*_glUniform1iv)(GLint location, GLsizei count, const GLint* v) = NULL; + static void (*_glUniform2f)(GLint location, GLfloat x, GLfloat y) FP_ATTRIB = NULL; ++static void (*_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform2i)(GLint location, GLint x, GLint y) = NULL; ++static void (*_glUniform2iv)(GLint location, GLsizei count, const GLint* v) = NULL; + static void (*_glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) FP_ATTRIB = NULL; ++static void (*_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform3i)(GLint location, GLint x, GLint y, GLint z) = NULL; ++static void (*_glUniform3iv)(GLint location, GLsizei count, const GLint* v) = NULL; + static void (*_glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FP_ATTRIB = NULL; ++static void (*_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) = NULL; ++static void (*_glUniform4iv)(GLint location, GLsizei count, const GLint* v) = NULL; ++static void (*_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; ++static void (*_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; ++static void (*_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; ++static void (*_glUseProgram)(GLuint program) = NULL; ++static void (*_glValidateProgram)(GLuint program) = NULL; + static void (*_glVertexAttrib1f)(GLuint indx, GLfloat x) FP_ATTRIB = NULL; ++static void (*_glVertexAttrib1fv)(GLuint indx, const GLfloat* values) = NULL; + static void (*_glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) FP_ATTRIB = NULL; ++static void (*_glVertexAttrib2fv)(GLuint indx, const GLfloat* values) = NULL; + static void (*_glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) FP_ATTRIB = NULL; ++static void (*_glVertexAttrib3fv)(GLuint indx, const GLfloat* values) = NULL; + static void (*_glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FP_ATTRIB = NULL; +-static void (*_glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) = NULL; ++static void (*_glVertexAttrib4fv)(GLuint indx, const GLfloat* values) = NULL; ++static void (*_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) = NULL; ++static void (*_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; ++static void (*_glEGLImageTargetTexture2DOES) (GLenum target, GLeglImageOES image) = NULL; + + + #define GLES2_LOAD(sym) { *(&_ ## sym) = (void *) android_dlsym(_libglesv2, #sym); } + +-/* +-This generates a function that when first called overwrites it's plt entry with new address. Subsequent calls jump directly at the target function in the android library. This means effectively 0 call overhead after the first call. +-*/ +- +-#define GLES2_IDLOAD(sym) \ +- __asm__ (".type " #sym ", %gnu_indirect_function"); \ +-typeof(sym) * sym ## _dispatch (void) __asm__ (#sym);\ +-typeof(sym) * sym ## _dispatch (void) \ +-{ \ +- return (void *) android_dlsym(_libglesv2, #sym); \ +-} +- + static void __attribute__((constructor)) _init_androidglesv2() { + _libglesv2 = (void *) android_dlopen(getenv("LIBGLESV2") ? getenv("LIBGLESV2") : "libGLESv2.so", RTLD_NOW); ++ GLES2_LOAD(glActiveTexture); ++ GLES2_LOAD(glAttachShader); ++ GLES2_LOAD(glBindAttribLocation); ++ GLES2_LOAD(glBindBuffer); ++ GLES2_LOAD(glBindFramebuffer); ++ GLES2_LOAD(glBindRenderbuffer); ++ GLES2_LOAD(glBindTexture); + GLES2_LOAD(glBlendColor); ++ GLES2_LOAD(glBlendEquation); ++ GLES2_LOAD(glBlendEquationSeparate); ++ GLES2_LOAD(glBlendFunc); ++ GLES2_LOAD(glBlendFuncSeparate); ++ GLES2_LOAD(glBufferData); ++ GLES2_LOAD(glBufferSubData); ++ GLES2_LOAD(glCheckFramebufferStatus); ++ GLES2_LOAD(glClear); + GLES2_LOAD(glClearColor); + GLES2_LOAD(glClearDepthf); ++ GLES2_LOAD(glClearStencil); ++ GLES2_LOAD(glColorMask); ++ GLES2_LOAD(glCompileShader); ++ GLES2_LOAD(glCompressedTexImage2D); ++ GLES2_LOAD(glCompressedTexSubImage2D); ++ GLES2_LOAD(glCopyTexImage2D); ++ GLES2_LOAD(glCopyTexSubImage2D); ++ GLES2_LOAD(glCreateProgram); ++ GLES2_LOAD(glCreateShader); ++ GLES2_LOAD(glCullFace); ++ GLES2_LOAD(glDeleteBuffers); ++ GLES2_LOAD(glDeleteFramebuffers); ++ GLES2_LOAD(glDeleteProgram); ++ GLES2_LOAD(glDeleteRenderbuffers); ++ GLES2_LOAD(glDeleteShader); ++ GLES2_LOAD(glDeleteTextures); ++ GLES2_LOAD(glDepthFunc); ++ GLES2_LOAD(glDepthMask); + GLES2_LOAD(glDepthRangef); ++ GLES2_LOAD(glDetachShader); ++ GLES2_LOAD(glDisable); ++ GLES2_LOAD(glDisableVertexAttribArray); ++ GLES2_LOAD(glDrawArrays); ++ GLES2_LOAD(glDrawElements); ++ GLES2_LOAD(glEnable); ++ GLES2_LOAD(glEnableVertexAttribArray); ++ GLES2_LOAD(glFinish); ++ GLES2_LOAD(glFlush); ++ GLES2_LOAD(glFramebufferRenderbuffer); ++ GLES2_LOAD(glFramebufferTexture2D); ++ GLES2_LOAD(glFrontFace); ++ GLES2_LOAD(glGenBuffers); ++ GLES2_LOAD(glGenerateMipmap); ++ GLES2_LOAD(glGenFramebuffers); ++ GLES2_LOAD(glGenRenderbuffers); ++ GLES2_LOAD(glGenTextures); ++ GLES2_LOAD(glGetActiveAttrib); ++ GLES2_LOAD(glGetActiveUniform); ++ GLES2_LOAD(glGetAttachedShaders); ++ GLES2_LOAD(glGetAttribLocation); ++ GLES2_LOAD(glGetBooleanv); ++ GLES2_LOAD(glGetBufferParameteriv); ++ GLES2_LOAD(glGetError); ++ GLES2_LOAD(glGetFloatv); ++ GLES2_LOAD(glGetFramebufferAttachmentParameteriv); ++ GLES2_LOAD(glGetIntegerv); ++ GLES2_LOAD(glGetProgramiv); ++ GLES2_LOAD(glGetProgramInfoLog); ++ GLES2_LOAD(glGetRenderbufferParameteriv); ++ GLES2_LOAD(glGetShaderiv); ++ GLES2_LOAD(glGetShaderInfoLog); ++ GLES2_LOAD(glGetShaderPrecisionFormat); ++ GLES2_LOAD(glGetShaderSource); ++ GLES2_LOAD(glGetString); ++ GLES2_LOAD(glGetTexParameterfv); ++ GLES2_LOAD(glGetTexParameteriv); ++ GLES2_LOAD(glGetUniformfv); ++ GLES2_LOAD(glGetUniformiv); ++ GLES2_LOAD(glGetUniformLocation); ++ GLES2_LOAD(glGetVertexAttribfv); ++ GLES2_LOAD(glGetVertexAttribiv); ++ GLES2_LOAD(glGetVertexAttribPointerv); ++ GLES2_LOAD(glHint); ++ GLES2_LOAD(glIsBuffer); ++ GLES2_LOAD(glIsEnabled); ++ GLES2_LOAD(glIsFramebuffer); ++ GLES2_LOAD(glIsProgram); ++ GLES2_LOAD(glIsRenderbuffer); ++ GLES2_LOAD(glIsShader); ++ GLES2_LOAD(glIsTexture); + GLES2_LOAD(glLineWidth); ++ GLES2_LOAD(glLinkProgram); ++ GLES2_LOAD(glPixelStorei); + GLES2_LOAD(glPolygonOffset); ++ GLES2_LOAD(glReadPixels); ++ GLES2_LOAD(glReleaseShaderCompiler); ++ GLES2_LOAD(glRenderbufferStorage); + GLES2_LOAD(glSampleCoverage); ++ GLES2_LOAD(glScissor); ++ GLES2_LOAD(glShaderBinary); ++ GLES2_LOAD(glShaderSource); ++ GLES2_LOAD(glStencilFunc); ++ GLES2_LOAD(glStencilFuncSeparate); ++ GLES2_LOAD(glStencilMask); ++ GLES2_LOAD(glStencilMaskSeparate); ++ GLES2_LOAD(glStencilOp); ++ GLES2_LOAD(glStencilOpSeparate); ++ GLES2_LOAD(glTexImage2D); + GLES2_LOAD(glTexParameterf); ++ GLES2_LOAD(glTexParameterfv); ++ GLES2_LOAD(glTexParameteri); ++ GLES2_LOAD(glTexParameteriv); ++ GLES2_LOAD(glTexSubImage2D); + GLES2_LOAD(glUniform1f); ++ GLES2_LOAD(glUniform1fv); ++ GLES2_LOAD(glUniform1i); ++ GLES2_LOAD(glUniform1iv); + GLES2_LOAD(glUniform2f); ++ GLES2_LOAD(glUniform2fv); ++ GLES2_LOAD(glUniform2i); ++ GLES2_LOAD(glUniform2iv); + GLES2_LOAD(glUniform3f); ++ GLES2_LOAD(glUniform3fv); ++ GLES2_LOAD(glUniform3i); ++ GLES2_LOAD(glUniform3iv); + GLES2_LOAD(glUniform4f); ++ GLES2_LOAD(glUniform4fv); ++ GLES2_LOAD(glUniform4i); ++ GLES2_LOAD(glUniform4iv); ++ GLES2_LOAD(glUniformMatrix2fv); ++ GLES2_LOAD(glUniformMatrix3fv); ++ GLES2_LOAD(glUniformMatrix4fv); ++ GLES2_LOAD(glUseProgram); ++ GLES2_LOAD(glValidateProgram); + GLES2_LOAD(glVertexAttrib1f); ++ GLES2_LOAD(glVertexAttrib1fv); + GLES2_LOAD(glVertexAttrib2f); ++ GLES2_LOAD(glVertexAttrib2fv); + GLES2_LOAD(glVertexAttrib3f); ++ GLES2_LOAD(glVertexAttrib3fv); + GLES2_LOAD(glVertexAttrib4f); ++ GLES2_LOAD(glVertexAttrib4fv); ++ GLES2_LOAD(glVertexAttribPointer); ++ GLES2_LOAD(glViewport); + GLES2_LOAD(glEGLImageTargetTexture2DOES); ++ + } + + +-GLES2_IDLOAD(glActiveTexture); ++void glActiveTexture (GLenum texture) ++{ ++ (*_glActiveTexture)(texture); ++} + +-GLES2_IDLOAD(glAttachShader); ++void glAttachShader (GLuint program, GLuint shader) ++{ ++ (*_glAttachShader)(program, shader); ++} + +-GLES2_IDLOAD(glBindAttribLocation); ++void glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) ++{ ++ (*_glBindAttribLocation)(program, index, name); ++} + +-GLES2_IDLOAD(glBindBuffer); ++void glBindBuffer (GLenum target, GLuint buffer) ++{ ++ (*_glBindBuffer)(target, buffer); ++} + +-GLES2_IDLOAD(glBindFramebuffer); ++void glBindFramebuffer (GLenum target, GLuint framebuffer) ++{ ++ (*_glBindFramebuffer)(target, framebuffer); ++} + +-GLES2_IDLOAD(glBindRenderbuffer); ++void glBindRenderbuffer (GLenum target, GLuint renderbuffer) ++{ ++ (*_glBindRenderbuffer)(target, renderbuffer); ++} + +-GLES2_IDLOAD(glBindTexture); ++void glBindTexture (GLenum target, GLuint texture) ++{ ++ (*_glBindTexture)(target, texture); ++} + +-GLES2_IDLOAD(glBlendEquation); ++void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++{ ++ (*_glBlendColor)(red, green, blue, alpha); ++} + +-GLES2_IDLOAD(glBlendEquationSeparate); ++void glBlendEquation ( GLenum mode ) ++{ ++ (*_glBlendEquation)(mode); ++} + +-GLES2_IDLOAD(glBlendFunc); ++void glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) ++{ ++ (*_glBlendEquationSeparate)(modeRGB, modeAlpha); ++} + +-GLES2_IDLOAD(glBlendFuncSeparate); ++void glBlendFunc (GLenum sfactor, GLenum dfactor) ++{ ++ (*_glBlendFunc)(sfactor, dfactor); ++} + +-GLES2_IDLOAD(glBufferData); ++void glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) ++{ ++ (*_glBlendFuncSeparate)(srcRGB, dstRGB, srcAlpha, dstAlpha); ++} + +-GLES2_IDLOAD(glBufferSubData); ++void glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) ++{ ++ (*_glBufferData)(target, size, data, usage); ++} + +-GLES2_IDLOAD(glCheckFramebufferStatus); ++void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) ++{ ++ (*_glBufferSubData)(target, offset, size, data); ++} + +-GLES2_IDLOAD(glClear); ++GLenum glCheckFramebufferStatus (GLenum target) ++{ ++ return (*_glCheckFramebufferStatus)(target); ++} + +-GLES2_IDLOAD(glClearStencil); ++void glClear (GLbitfield mask) ++{ ++ (*_glClear)(mask); ++} + +-GLES2_IDLOAD(glColorMask); ++void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++{ ++ (*_glClearColor)(red, green, blue, alpha); ++} + +-GLES2_IDLOAD(glCompileShader); ++void glClearDepthf (GLclampf depth) ++{ ++ (*_glClearDepthf)(depth); ++} + +-GLES2_IDLOAD(glCompressedTexImage2D); ++void glClearStencil (GLint s) ++{ ++ (*_glClearStencil)(s); ++} + +-GLES2_IDLOAD(glCompressedTexSubImage2D); ++void glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) ++{ ++ (*_glColorMask)(red, green, blue, alpha); ++} + +-GLES2_IDLOAD(glCopyTexImage2D); ++void glCompileShader (GLuint shader) ++{ ++ (*_glCompileShader)(shader); ++} + +-GLES2_IDLOAD(glCopyTexSubImage2D); ++void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) ++{ ++ (*_glCompressedTexImage2D)(target, level, internalformat, width, height, border, imageSize, data); ++} + +-GLES2_IDLOAD(glCreateProgram); ++void glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) ++{ ++ (*_glCompressedTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, imageSize, data); ++} + +-GLES2_IDLOAD(glCreateShader); ++void glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) ++{ ++ (*_glCopyTexImage2D)(target, level, internalformat, x, y, width, height, border); ++} + +-GLES2_IDLOAD(glCullFace); ++void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) ++{ ++ (*_glCopyTexSubImage2D)(target, level, xoffset, yoffset, x, y, width, height); ++} + +-GLES2_IDLOAD(glDeleteBuffers); ++GLuint glCreateProgram (void) ++{ ++ return (*_glCreateProgram)(); ++} + +-GLES2_IDLOAD(glDeleteFramebuffers); ++GLuint glCreateShader (GLenum type) ++{ ++ return (*_glCreateShader)(type); ++} + +-GLES2_IDLOAD(glDeleteProgram); ++void glCullFace (GLenum mode) ++{ ++ (*_glCullFace)(mode); ++} + +-GLES2_IDLOAD(glDeleteRenderbuffers); ++void glDeleteBuffers (GLsizei n, const GLuint* buffers) ++{ ++ (*_glDeleteBuffers)(n, buffers); ++} + +-GLES2_IDLOAD(glDeleteShader); ++void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) ++{ ++ (*_glDeleteFramebuffers)(n, framebuffers); ++} + +-GLES2_IDLOAD(glDeleteTextures); ++void glDeleteProgram (GLuint program) ++{ ++ (*_glDeleteProgram)(program); ++} + +-GLES2_IDLOAD(glDepthFunc); ++void glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) ++{ ++ (*_glDeleteRenderbuffers)(n, renderbuffers); ++} + +-GLES2_IDLOAD(glDepthMask); ++void glDeleteShader (GLuint shader) ++{ ++ (*_glDeleteShader)(shader); ++} + +-GLES2_IDLOAD(glDetachShader); ++void glDeleteTextures (GLsizei n, const GLuint* textures) ++{ ++ (*_glDeleteTextures)(n, textures); ++} + +-GLES2_IDLOAD(glDisable); ++void glDepthFunc (GLenum func) ++{ ++ (*_glDepthFunc)(func); ++} + +-GLES2_IDLOAD(glDisableVertexAttribArray); ++void glDepthMask (GLboolean flag) ++{ ++ (*_glDepthMask)(flag); ++} + +-GLES2_IDLOAD(glDrawArrays); ++void glDepthRangef (GLclampf zNear, GLclampf zFar) ++{ ++ (*_glDepthRangef)(zNear, zFar); ++} + +-GLES2_IDLOAD(glDrawElements); ++void glDetachShader (GLuint program, GLuint shader) ++{ ++ (*_glDetachShader)(program, shader); ++} + +-GLES2_IDLOAD(glEnable); ++void glDisable (GLenum cap) ++{ ++ (*_glDisable)(cap); ++} + +-GLES2_IDLOAD(glEnableVertexAttribArray); ++void glDisableVertexAttribArray (GLuint index) ++{ ++ (*_glDisableVertexAttribArray)(index); ++} + +-GLES2_IDLOAD(glFinish); ++void glDrawArrays (GLenum mode, GLint first, GLsizei count) ++{ ++ (*_glDrawArrays)(mode, first, count); ++} + +-GLES2_IDLOAD(glFlush); ++void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) ++{ ++ (*_glDrawElements)(mode, count, type, indices); ++} + +-GLES2_IDLOAD(glFramebufferRenderbuffer); ++void glEnable (GLenum cap) ++{ ++ (*_glEnable)(cap); ++} + +-GLES2_IDLOAD(glFramebufferTexture2D); ++void glEnableVertexAttribArray (GLuint index) ++{ ++ (*_glEnableVertexAttribArray)(index); ++} + +-GLES2_IDLOAD(glFrontFace); ++void glFinish (void) ++{ ++ (*_glFinish)(); ++} + +-GLES2_IDLOAD(glGenBuffers); ++void glFlush (void) ++{ ++ (*_glFlush)(); ++} + +-GLES2_IDLOAD(glGenerateMipmap); ++void glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) ++{ ++ (*_glFramebufferRenderbuffer)(target, attachment, renderbuffertarget, renderbuffer); ++} + +-GLES2_IDLOAD(glGenFramebuffers); ++void glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) ++{ ++ (*_glFramebufferTexture2D)(target, attachment, textarget, texture, level); ++} + +-GLES2_IDLOAD(glGenRenderbuffers); ++void glFrontFace (GLenum mode) ++{ ++ (*_glFrontFace)(mode); ++} + +-GLES2_IDLOAD(glGenTextures); ++void glGenBuffers (GLsizei n, GLuint* buffers) ++{ ++ (*_glGenBuffers)(n, buffers); ++} + +-GLES2_IDLOAD(glGetActiveAttrib); ++void glGenerateMipmap (GLenum target) ++{ ++ (*_glGenerateMipmap)(target); ++} + +-GLES2_IDLOAD(glGetActiveUniform); ++void glGenFramebuffers (GLsizei n, GLuint* framebuffers) ++{ ++ (*_glGenFramebuffers)(n, framebuffers); ++} + +-GLES2_IDLOAD(glGetAttachedShaders); ++void glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) ++{ ++ (*_glGenRenderbuffers)(n, renderbuffers); ++} + +-GLES2_IDLOAD(glGetAttribLocation); ++void glGenTextures (GLsizei n, GLuint* textures) ++{ ++ (*_glGenTextures)(n, textures); ++} + +-GLES2_IDLOAD(glGetBooleanv); ++void glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) ++{ ++ (*_glGetActiveAttrib)(program, index, bufsize, length, size, type, name); ++} + +-GLES2_IDLOAD(glGetBufferParameteriv); ++void glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) ++{ ++ (*_glGetActiveUniform)(program, index, bufsize, length, size, type, name); ++} + +-GLES2_IDLOAD(glGetError); ++void glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) ++{ ++ (*_glGetAttachedShaders)(program, maxcount, count, shaders); ++} + +-GLES2_IDLOAD(glGetFloatv); ++int glGetAttribLocation (GLuint program, const GLchar* name) ++{ ++ (*_glGetAttribLocation)(program, name); ++} + +-GLES2_IDLOAD(glGetFramebufferAttachmentParameteriv); ++void glGetBooleanv (GLenum pname, GLboolean* params) ++{ ++ (*_glGetBooleanv)(pname, params); ++} + +-GLES2_IDLOAD(glGetIntegerv); ++void glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params) ++{ ++ (*_glGetBufferParameteriv)(target, pname, params); ++} + +-GLES2_IDLOAD(glGetProgramiv); ++GLenum glGetError (void) ++{ ++ return (*_glGetError)(); ++} + +-GLES2_IDLOAD(glGetProgramInfoLog); ++void glGetFloatv (GLenum pname, GLfloat* params) ++{ ++ (*_glGetFloatv)(pname, params); ++} + +-GLES2_IDLOAD(glGetRenderbufferParameteriv); ++void glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) ++{ ++ (*_glGetFramebufferAttachmentParameteriv)(target, attachment, pname, params); ++} + +-GLES2_IDLOAD(glGetShaderiv); ++void glGetIntegerv (GLenum pname, GLint* params) ++{ ++ (*_glGetIntegerv)(pname, params); ++} + +-GLES2_IDLOAD(glGetShaderInfoLog); ++void glGetProgramiv (GLuint program, GLenum pname, GLint* params) ++{ ++ (*_glGetProgramiv)(program, pname, params); ++} + +-GLES2_IDLOAD(glGetShaderPrecisionFormat); ++void glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) ++{ ++ (*_glGetProgramInfoLog)(program, bufsize, length, infolog); ++} + +-GLES2_IDLOAD(glGetShaderSource); ++void glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) ++{ ++ (*_glGetRenderbufferParameteriv)(target, pname, params); ++} + +-GLES2_IDLOAD(glGetString); ++void glGetShaderiv (GLuint shader, GLenum pname, GLint* params) ++{ ++ (*_glGetShaderiv)(shader, pname, params); ++} + +-GLES2_IDLOAD(glGetTexParameterfv); ++void glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) ++{ ++ (*_glGetShaderInfoLog)(shader, bufsize, length, infolog); ++} + +-GLES2_IDLOAD(glGetTexParameteriv); ++void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) ++{ ++ (*_glGetShaderPrecisionFormat)(shadertype, precisiontype, range, precision); ++} + +-GLES2_IDLOAD(glGetUniformfv); ++void glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) ++{ ++ (*_glGetShaderSource)(shader, bufsize, length, source); ++} + +-GLES2_IDLOAD(glGetUniformiv); ++const GLubyte* glGetString (GLenum name) ++{ ++ // Return 2.0 even though drivers might actually support 3.0 or higher, ++ // because libhybris does not provide any 3.0+ symbols. ++ if (name == GL_VERSION) { ++ static GLubyte glGetString_versionString[64]; ++ snprintf(glGetString_versionString, sizeof(glGetString_versionString), "OpenGL ES 2.0 (%s)", (*_glGetString)(name)); ++ return glGetString_versionString; ++ } + +-GLES2_IDLOAD(glGetUniformLocation); ++ (*_glGetString)(name); ++} + +-GLES2_IDLOAD(glGetVertexAttribfv); ++void glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params) ++{ ++ (*_glGetTexParameterfv)(target, pname, params); ++} + +-GLES2_IDLOAD(glGetVertexAttribiv); ++void glGetTexParameteriv (GLenum target, GLenum pname, GLint* params) ++{ ++ (*_glGetTexParameteriv)(target, pname, params); ++} + +-GLES2_IDLOAD(glGetVertexAttribPointerv); ++void glGetUniformfv (GLuint program, GLint location, GLfloat* params) ++{ ++ (*_glGetUniformfv)(program, location, params); ++} + +-GLES2_IDLOAD(glHint); ++void glGetUniformiv (GLuint program, GLint location, GLint* params) ++{ ++ (*_glGetUniformiv)(program, location, params); ++} + +-GLES2_IDLOAD(glIsBuffer); ++int glGetUniformLocation (GLuint program, const GLchar* name) ++{ ++ (*_glGetUniformLocation)(program, name); ++} + +-GLES2_IDLOAD(glIsEnabled); ++void glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) ++{ ++ (*_glGetVertexAttribfv)(index, pname, params); ++} + +-GLES2_IDLOAD(glIsFramebuffer); ++void glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params) ++{ ++ (*_glGetVertexAttribiv)(index, pname, params); ++} + +-GLES2_IDLOAD(glIsProgram); ++void glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer) ++{ ++ (*_glGetVertexAttribPointerv)(index, pname, pointer); ++} + +-GLES2_IDLOAD(glIsRenderbuffer); ++void glHint (GLenum target, GLenum mode) ++{ ++ (*_glHint)(target, mode); ++} + +-GLES2_IDLOAD(glIsShader); ++GLboolean glIsBuffer (GLuint buffer) ++{ ++ return (*_glIsBuffer)(buffer); ++} + +-GLES2_IDLOAD(glIsTexture); ++GLboolean glIsEnabled (GLenum cap) ++{ ++ return (*_glIsEnabled)(cap); ++} + +-GLES2_IDLOAD(glLinkProgram); ++GLboolean glIsFramebuffer (GLuint framebuffer) ++{ ++ return (*_glIsFramebuffer)(framebuffer); ++} + +-GLES2_IDLOAD(glPixelStorei); ++GLboolean glIsProgram (GLuint program) ++{ ++ return (*_glIsProgram)(program); ++} + +-GLES2_IDLOAD(glReadPixels); ++GLboolean glIsRenderbuffer (GLuint renderbuffer) ++{ ++ return (*_glIsRenderbuffer)(renderbuffer); ++} + +-GLES2_IDLOAD(glReleaseShaderCompiler); ++GLboolean glIsShader (GLuint shader) ++{ ++ return (*_glIsShader)(shader); ++} + +-GLES2_IDLOAD(glRenderbufferStorage); ++GLboolean glIsTexture (GLuint texture) ++{ ++ return (*_glIsTexture)(texture); ++} + +-GLES2_IDLOAD(glScissor); ++void glLineWidth (GLfloat width) ++{ ++ (*_glLineWidth)(width); ++} + +-GLES2_IDLOAD(glShaderBinary); ++void glLinkProgram (GLuint program) ++{ ++ (*_glLinkProgram)(program); ++} + +-GLES2_IDLOAD(glShaderSource); ++void glPixelStorei (GLenum pname, GLint param) ++{ ++ (*_glPixelStorei)(pname, param); ++} + +-GLES2_IDLOAD(glStencilFunc); ++void glPolygonOffset (GLfloat factor, GLfloat units) ++{ ++ (*_glPolygonOffset)(factor, units); ++} + +-GLES2_IDLOAD(glStencilFuncSeparate); ++void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) ++{ ++ (*_glReadPixels)(x, y, width, height, format, type, pixels); + +-GLES2_IDLOAD(glStencilMask); ++} + +-GLES2_IDLOAD(glStencilMaskSeparate); ++void glReleaseShaderCompiler (void) ++{ ++ (*_glReleaseShaderCompiler)(); ++} + +-GLES2_IDLOAD(glStencilOp); ++void glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) ++{ ++ (*_glRenderbufferStorage)(target, internalformat, width, height); ++} + +-GLES2_IDLOAD(glStencilOpSeparate); ++void glSampleCoverage (GLclampf value, GLboolean invert) ++{ ++ (*_glSampleCoverage)(value, invert); ++} + +-GLES2_IDLOAD(glTexImage2D); ++void glScissor (GLint x, GLint y, GLsizei width, GLsizei height) ++{ ++ (*_glScissor)(x, y, width, height); ++} + +-GLES2_IDLOAD(glTexParameterfv); ++void glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) ++{ ++ (*_glShaderBinary)(n, shaders, binaryformat, binary, length); ++} + +-GLES2_IDLOAD(glTexParameteri); ++void glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) ++{ ++ (*_glShaderSource)(shader, count, string, length); ++} + +-GLES2_IDLOAD(glTexParameteriv); ++void glStencilFunc (GLenum func, GLint ref, GLuint mask) ++{ ++ (*_glStencilFunc)(func, ref, mask); ++} + +-GLES2_IDLOAD(glTexSubImage2D); ++void glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) ++{ ++ (*_glStencilFuncSeparate)(face, func, ref, mask); ++} + +-GLES2_IDLOAD(glUniform1fv); ++void glStencilMask (GLuint mask) ++{ ++ (*_glStencilMask)(mask); ++} + +-GLES2_IDLOAD(glUniform1i); ++void glStencilMaskSeparate (GLenum face, GLuint mask) ++{ ++ (*_glStencilMaskSeparate)(face, mask); ++} + +-GLES2_IDLOAD(glUniform1iv); ++void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) ++{ ++ (*_glStencilOp)(fail, zfail, zpass); ++} + +-GLES2_IDLOAD(glUniform2fv); ++void glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) ++{ ++ (*_glStencilOpSeparate)(face, fail, zfail, zpass); ++} + +-GLES2_IDLOAD(glUniform2i); ++void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) ++{ ++ (*_glTexImage2D)(target, level, internalformat, width, height, border, format, type, pixels); ++} + +-GLES2_IDLOAD(glUniform2iv); ++void glTexParameterf (GLenum target, GLenum pname, GLfloat param) ++{ ++ (*_glTexParameterf)(target, pname, param); ++} + +-GLES2_IDLOAD(glUniform3fv); ++void glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params) ++{ ++ (*_glTexParameterfv)(target, pname, params); ++} + +-GLES2_IDLOAD(glUniform3i); ++void glTexParameteri (GLenum target, GLenum pname, GLint param) ++{ ++ (*_glTexParameteri)(target, pname, param); ++} + +-GLES2_IDLOAD(glUniform3iv); ++void glTexParameteriv (GLenum target, GLenum pname, const GLint* params) ++{ ++ (*_glTexParameteriv)(target, pname, params); ++} + +-GLES2_IDLOAD(glUniform4fv); ++void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) ++{ ++ (*_glTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, type, pixels); ++} + +-GLES2_IDLOAD(glUniform4i); ++void glUniform1f (GLint location, GLfloat x) ++{ ++ (*_glUniform1f)(location, x); ++} + +-GLES2_IDLOAD(glUniform4iv); ++void glUniform1fv (GLint location, GLsizei count, const GLfloat* v) ++{ ++ (*_glUniform1fv)(location, count, v); ++} + +-GLES2_IDLOAD(glUniformMatrix2fv); ++void glUniform1i (GLint location, GLint x) ++{ ++ (*_glUniform1i)(location, x); ++} -@@ -55,10 +75,10 @@ struct link_map - /* needed for dl_iterate_phdr to be passed to the callbacks provided */ - struct dl_phdr_info - { -- Elf32_Addr dlpi_addr; -+ Elf_Addr dlpi_addr; - const char *dlpi_name; -- const Elf32_Phdr *dlpi_phdr; -- Elf32_Half dlpi_phnum; -+ const Elf_Phdr *dlpi_phdr; -+ Elf_Half dlpi_phnum; - }; +-GLES2_IDLOAD(glUniformMatrix3fv); ++void glUniform1iv (GLint location, GLsizei count, const GLint* v) ++{ ++ (*_glUniform1iv)(location, count, v); ++} +-GLES2_IDLOAD(glUniformMatrix4fv); ++void glUniform2f (GLint location, GLfloat x, GLfloat y) ++{ ++ (*_glUniform2f)(location, x, y); ++} -@@ -90,7 +110,7 @@ typedef struct soinfo soinfo; - struct soinfo - { - const char name[SOINFO_NAME_LEN]; -- Elf32_Phdr *phdr; -+ Elf_Phdr *phdr; - int phnum; - unsigned entry; - unsigned base; -@@ -107,7 +127,7 @@ struct soinfo - unsigned flags; +-GLES2_IDLOAD(glUseProgram); ++void glUniform2fv (GLint location, GLsizei count, const GLfloat* v) ++{ ++ (*_glUniform2fv)(location, count, v); ++} - const char *strtab; -- Elf32_Sym *symtab; -+ Elf_Sym *symtab; +-GLES2_IDLOAD(glValidateProgram); ++void glUniform2i (GLint location, GLint x, GLint y) ++{ ++ (*_glUniform2i)(location, x, y); ++} - unsigned nbucket; - unsigned nchain; -@@ -116,10 +136,10 @@ struct soinfo +-GLES2_IDLOAD(glVertexAttrib1fv); ++void glUniform2iv (GLint location, GLsizei count, const GLint* v) ++{ ++ (*_glUniform2iv)(location, count, v); ++} - unsigned *plt_got; +-GLES2_IDLOAD(glVertexAttrib2fv); ++void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) ++{ ++ (*_glUniform3f)(location, x, y, z); ++} -- Elf32_Rel *plt_rel; -+ Elf_Rel *plt_rel; - unsigned plt_rel_count; +-GLES2_IDLOAD(glVertexAttrib3fv); ++void glUniform3fv (GLint location, GLsizei count, const GLfloat* v) ++{ ++ (*_glUniform3fv)(location, count, v); ++} -- Elf32_Rel *rel; -+ Elf_Rel *rel; - unsigned rel_count; +-GLES2_IDLOAD(glVertexAttrib4fv); ++void glUniform3i (GLint location, GLint x, GLint y, GLint z) ++{ ++ (*_glUniform3i)(location, x, y, z); ++} - unsigned *preinit_array; -@@ -144,7 +164,7 @@ struct soinfo +-GLES2_IDLOAD(glVertexAttribPointer); ++void glUniform3iv (GLint location, GLsizei count, const GLint* v) ++{ ++ (*_glUniform3iv)(location, count, v); ++} - int constructors_called; +-GLES2_IDLOAD(glViewport); ++void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++{ ++ (*_glUniform4f)(location, x, y, z, w); ++} -- Elf32_Addr gnu_relro_start; -+ Elf_Addr gnu_relro_start; - unsigned gnu_relro_len; +-void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) ++void glUniform4fv (GLint location, GLsizei count, const GLfloat* v) + { +- struct egl_image *img = image; +- return (*_glEGLImageTargetTexture2DOES)(target, img ? img->egl_image : NULL); ++ (*_glUniform4fv)(location, count, v); + } - }; -@@ -202,18 +222,17 @@ extern soinfo libdl_info; +-void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++void glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) + { +- return (*_glBlendColor)(red, green, blue, alpha); ++ (*_glUniform4i)(location, x, y, z, w); + } - soinfo *find_library(const char *name); - unsigned unload_library(soinfo *si); --Elf32_Sym *lookup_in_library(soinfo *si, const char *name); --Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); -+Elf_Sym *lookup_in_library(soinfo *si, const char *name); -+Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start); - soinfo *find_containing_library(const void *addr); --Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); -+Elf_Sym *find_containing_symbol(const void *addr, soinfo *si); - const char *linker_get_error(void); - void call_constructors_recursive(soinfo *si); +-void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++void glUniform4iv (GLint location, GLsizei count, const GLint* v) + { +- return (*_glVertexAttrib4f)(indx, x, y, z, w); ++ (*_glUniform4iv)(location, count, v); + } -+int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); - #ifdef ANDROID_ARM_LINKER - typedef long unsigned int *_Unwind_Ptr; - _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); --#elif defined(ANDROID_X86_LINKER) --int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); - #endif +-void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) ++void glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { +- return (*_glVertexAttrib2f)(indx, x, y); ++ (*_glUniformMatrix2fv)(location, count, transpose, value); + } - #endif ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker_format.c -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker_format.c -@@ -268,7 +268,7 @@ static int log_vprint(int prio, const ch - result = vformat_buffer(buf, sizeof buf, fmt, args); +-void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) ++void glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { +- return (*_glVertexAttrib3f)(indx, x, y, z); ++ (*_glUniformMatrix3fv)(location, count, transpose, value); + } - if (log_fd < 0) { -- log_fd = open("/dev/log/main", O_WRONLY); -+ log_fd = open("/dev/alog/main", O_WRONLY); - if (log_fd < 0) { - log_fd = fileno(stdout); // kernel doesn't have android log - return result; ---- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/configure.ac -+++ libhybris-0.1.0+git20151016+6d424c9/hybris/configure.ac -@@ -73,6 +73,13 @@ AC_ARG_ENABLE(wayland_serverside_buffers - [wayland_serverside_buffers=yes]) - AM_CONDITIONAL( [WANT_WL_SERVERSIDE_BUFFERS], [test x"$wayland_serverside_buffers" = x"yes"]) ++void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) ++{ ++ (*_glUniformMatrix4fv)(location, count, transpose, value); ++} -+AC_ARG_ENABLE(property_cache, -+ [ --enable-property-cache Enable runtime android property cache (default=disabled)], -+ [property_cache=$enableval], -+ [property_cache=no]) -+AM_CONDITIONAL( [WANT_RUNTIME_PROPERTY_CACHE], [test x"$property_cache" = x"yes"]) +-void glVertexAttrib1f (GLuint indx, GLfloat x) ++void glUseProgram (GLuint program) + { +- return (*_glVertexAttrib1f)(indx, x); ++ (*_glUseProgram)(program); + } + +-void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++void glValidateProgram (GLuint program) + { +- return (*_glUniform4f)(location, x, y, z, w); ++ (*_glValidateProgram)(program); + } + +-void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) ++void glVertexAttrib1f (GLuint indx, GLfloat x) + { +- return (*_glUniform3f)(location, x, y, z); ++ (*_glVertexAttrib1f)(indx, x); + } + +-void glUniform2f (GLint location, GLfloat x, GLfloat y) ++void glVertexAttrib1fv (GLuint indx, const GLfloat* values) + { +- return (*_glUniform2f)(location, x, y); ++ (*_glVertexAttrib1fv)(indx, values); + } + +-void glUniform1f (GLint location, GLfloat x) ++void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) + { +- return (*_glUniform1f)(location, x); ++ (*_glVertexAttrib2f)(indx, x, y); + } + +-void glTexParameterf (GLenum target, GLenum pname, GLfloat param) ++void glVertexAttrib2fv (GLuint indx, const GLfloat* values) + { +- return (*_glTexParameterf)(target, pname, param); ++ (*_glVertexAttrib2fv)(indx, values); + } + +-void glSampleCoverage (GLclampf value, GLboolean invert) ++void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) + { +- return (*_glSampleCoverage)(value, invert); ++ (*_glVertexAttrib3f)(indx, x, y, z); + } +-void glPolygonOffset (GLfloat factor, GLfloat units) + ++void glVertexAttrib3fv (GLuint indx, const GLfloat* values) + { +- return (*_glPolygonOffset)(factor, units); ++ (*_glVertexAttrib3fv)(indx, values); + } +-void glDepthRangef (GLclampf zNear, GLclampf zFar) + - AC_ARG_ENABLE(arch, - [ --enable-arch[=arch] Compile specific CPU target(default=arm) - arm: compile for ARM -@@ -114,7 +121,10 @@ AC_ARG_WITH(android-headers, - AS_IF([test -f $withval/libnfc-nxp/phLibNfc.h], [ANDROID_HEADERS_CFLAGS="-I$withval -I$withval/libnfc-nxp"],[ANDROID_HEADERS_CFLAGS="-I$withval"]) - AC_SUBST([ANDROID_HEADERS_CFLAGS]) - ], -- [ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) ] -+ [ -+ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) -+ AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [false]) -+ ] - ) - CPPFLAGS="$CPPFLAGS $ANDROID_HEADERS_CFLAGS" ++void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + { +- return (*_glDepthRangef)(zNear, zFar); ++ (*_glVertexAttrib4f)(indx, x, y, z, w); + } -@@ -177,6 +187,11 @@ AM_CONDITIONAL([HAS_ANDROID_4_1_0], [tes - AM_CONDITIONAL([HAS_ANDROID_4_0_0], [test $android_headers_major -ge 4 -a $android_headers_minor -ge 0 ]) - AM_CONDITIONAL([HAS_ANDROID_2_3_0], [test $android_headers_major -ge 2 -a $android_headers_minor -ge 3 ]) ++void glVertexAttrib4fv (GLuint indx, const GLfloat* values) ++{ ++ (*_glVertexAttrib4fv)(indx, values); ++} + +-void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++void glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) + { +- return (*_glClearColor)(red, green, blue, alpha); ++ (*_glVertexAttribPointer)(indx, size, type, normalized, stride, ptr); + } + +-void glClearDepthf (GLclampf depth) ++void glViewport (GLint x, GLint y, GLsizei width, GLsizei height) + { +- return (*_glClearDepthf)(depth); ++ (*_glViewport)(x, y, width, height); + } +-void glLineWidth (GLfloat width) ++ ++void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) + { +- return (*_glLineWidth)(width); ++ (*_glEGLImageTargetTexture2DOES)(target, image); + } -+AC_ARG_ENABLE(mali-quirks, -+ [ --enable-mali-quirks Enable Mali GPU driver quirks (default=disabled)], -+ [mali_quirks=$enableval], -+ [mali_quirks="no"]) -+AM_CONDITIONAL([WANT_MALI_QUIRKS], [test x"$mali_quirks" = x"yes"]) - AC_CONFIG_FILES([ - Makefile -@@ -217,6 +232,10 @@ AC_CONFIG_FILES([ - camera/libcamera.pc - vibrator/Makefile - vibrator/libvibrator.pc -+ media/Makefile -+ media/libmedia.pc -+ wifi/Makefile -+ wifi/libwifi.pc - include/Makefile - utils/Makefile - tests/Makefile --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/hardware/hardware.c +++ libhybris-0.1.0+git20151016+6d424c9/hybris/hardware/hardware.c @@ -18,6 +18,7 @@ @@ -12130,6 +25304,13 @@ dlfcnincludedir = $(includedir)/hybris/dlfcn dlfcninclude_HEADERS = \ hybris/dlfcn/dlfcn.h +@@ -73,4 +87,5 @@ commonincludedir = $(includedir)/hybris/ + commoninclude_HEADERS = \ + hybris/common/binding.h \ + hybris/common/floating_point_abi.h \ +- hybris/common/dlfcn.h ++ hybris/common/dlfcn.h \ ++ hybris/common/hooks.h --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/camera/camera_compatibility_layer.h +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/camera/camera_compatibility_layer.h @@ -37,6 +37,12 @@ extern "C" { @@ -12350,6 +25531,53 @@ * * If you need macros with more arguments, just customize the * MAX_ARGS variable in generate_wrapper_macros.py. +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/common/dlfcn.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/dlfcn.h +@@ -25,7 +25,7 @@ extern "C" { + void *hybris_dlopen(const char *filename, int flag); + void *hybris_dlsym(void *handle, const char *symbol); + int hybris_dlclose(void *handle); +-char *hybris_dlerror(void); ++const char *hybris_dlerror(void); + + #ifdef __cplusplus + } +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/hooks.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2016 Canonical Ltd ++ * ++ * 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_HOOKS_H_ ++#define _HYBRIS_HOOKS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef void* (*hybris_hook_cb)(const char *symbol_name, const char *requester); ++ ++void hybris_set_hook_callback(hybris_hook_cb callback); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/input/input_stack_compatibility_layer.h +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/input/input_stack_compatibility_layer.h @@ -109,6 +109,7 @@ extern "C" { @@ -12396,7 +25624,7 @@ + android::sp preview_texture; +#endif + // From android::SurfaceTexture/GLConsumer::FrameAvailableListener -+#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 + void onFrameAvailable(const android::BufferItem& item); +#else void onFrameAvailable(); @@ -12921,7 +26149,7 @@ +#endif // MEDIA_FORMAT_LAYER_H_ --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_message_layer.h -@@ -0,0 +1,56 @@ +@@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 Canonical Ltd + * @@ -12946,6 +26174,7 @@ +#include + +#include ++#include +#include + +#ifdef __cplusplus @@ -13419,7 +26648,12 @@ --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/input/is.c +++ libhybris-0.1.0+git20151016+6d424c9/hybris/input/is.c -@@ -28,6 +28,14 @@ +@@ -24,10 +24,18 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libis_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libis_compat_layer.so" HYBRIS_LIBRARY_INITIALIZE(is, COMPAT_LIBRARY_PATH); @@ -13434,6 +26668,28 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(is, android_input_stack_initialize, struct AndroidEventListener*, struct InputStackConfiguration*); HYBRIS_IMPLEMENT_VOID_FUNCTION0(is, android_input_stack_start); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c +@@ -34,7 +34,7 @@ + + #include + +-HYBRIS_LIBRARY_INITIALIZE(libnfc_ndef_so, "/system/lib/libnfc_ndef.so"); ++HYBRIS_LIBRARY_INITIALIZE(libnfc_ndef_so, "libnfc_ndef.so"); + + HYBRIS_IMPLEMENT_FUNCTION5(libnfc_ndef_so, NFCSTATUS, phFriNfc_NdefRecord_GetRecords, uint8_t *, uint32_t, uint8_t **, uint8_t *, uint32_t *); + HYBRIS_IMPLEMENT_FUNCTION1(libnfc_ndef_so, uint32_t, phFriNfc_NdefRecord_GetLength, phFriNfc_NdefRecord_t *); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/libnfc_nxp/libnfc_nxp.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_nxp/libnfc_nxp.c +@@ -56,7 +56,7 @@ typedef void (*pphDal4Nfc_DeferFuncPoi + + #include + +-HYBRIS_LIBRARY_INITIALIZE(libnfc_so, "/system/lib/libnfc.so"); ++HYBRIS_LIBRARY_INITIALIZE(libnfc_so, "libnfc.so"); + + HYBRIS_IMPLEMENT_FUNCTION2(libnfc_so, NFCSTATUS, phLibNfc_Mgt_ConfigureDriver, pphLibNfc_sConfig_t, void **); + HYBRIS_IMPLEMENT_FUNCTION2(libnfc_so, NFCSTATUS, phDal4Nfc_Config, pphDal4Nfc_sConfig_t, void **); --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/hybris/media/Makefile.am @@ -0,0 +1,17 @@ @@ -13505,7 +26761,7 @@ +#include +#include + -+#define COMPAT_LIBRARY_PATH "/system/lib/libmedia_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libmedia_compat_layer.so" + +#ifdef __ARM_PCS_VFP +#define FP_ATTRIB __attribute__((pcs("aapcs"))) @@ -13929,8 +27185,21 @@ endif --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/properties/properties.c +++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties.c -@@ -167,8 +167,23 @@ int property_get(const char *key, char * - if ((key) && (strlen(key) >= PROP_NAME_MAX -1)) return -1; +@@ -151,7 +151,7 @@ static int property_get_socket(const cha + + /* In case it's null, just use the default */ + if ((strlen(msg.value) == 0) && (default_value)) { +- if (strlen(default_value) >= PROP_VALUE_MAX -1) return -1; ++ if (strlen(default_value) > PROP_VALUE_MAX -1) return -1; + strcpy(msg.value, default_value); + } + +@@ -164,11 +164,26 @@ int property_get(const char *key, char * + { + char *ret = NULL; + +- if ((key) && (strlen(key) >= PROP_NAME_MAX -1)) return -1; ++ if ((key) && (strlen(key) > PROP_NAME_MAX -1)) return -1; if (value == NULL) return -1; - if (property_get_socket(key, value, default_value) == 0) @@ -13955,17 +27224,21 @@ /* In case the socket is not available, search the property file cache by hand */ ret = hybris_propcache_find(key); -@@ -196,6 +211,10 @@ int property_set(const char *key, const - if (strlen(key) >= PROP_NAME_MAX -1) return -1; - if (strlen(value) >= PROP_VALUE_MAX -1) return -1; +@@ -193,8 +208,12 @@ int property_set(const char *key, const + if (key == 0) return -1; + if (value == 0) value = ""; +- if (strlen(key) >= PROP_NAME_MAX -1) return -1; +- if (strlen(value) >= PROP_VALUE_MAX -1) return -1; ++ if (strlen(key) > PROP_NAME_MAX -1) return -1; ++ if (strlen(value) > PROP_VALUE_MAX -1) return -1; ++ + runtime_cache_lock(); + runtime_cache_remove(key); + runtime_cache_unlock(); -+ + memset(&msg, 0, sizeof(msg)); msg.cmd = PROP_MSG_SETPROP; - strncpy(msg.name, key, sizeof(msg.name)); --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/properties/properties_p.h +++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties_p.h @@ -23,4 +23,18 @@ typedef void (*hybris_propcache_list_cb) @@ -14170,6 +27443,17 @@ + runtime_cache_ensure_initialized(); + runtime_cache_insert_impl(key, value); +} +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/sf/sf.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/sf/sf.c +@@ -24,7 +24,7 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libsf_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libsf_compat_layer.so" + + HYBRIS_LIBRARY_INITIALIZE(sf, COMPAT_LIBRARY_PATH); + --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/tests/Makefile.am +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/Makefile.am @@ -1,4 +1,5 @@ @@ -14210,7 +27494,7 @@ test_audio_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/hardware/libhardware.la -@@ -146,6 +147,28 @@ test_camera_LDADD = \ +@@ -146,8 +147,30 @@ test_camera_LDADD = \ $(top_builddir)/camera/libcamera.la \ $(top_builddir)/input/libis.la @@ -14237,8 +27521,23 @@ + $(top_builddir)/sf/libsf.la + test_gps_SOURCES = test_gps.c - test_gps_CFLAGS = -pthread \ +-test_gps_CFLAGS = -pthread \ ++test_gps_CFLAGS = \ -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) + +@@ -166,9 +189,9 @@ test_nfc_SOURCES = test_nfc.c + test_nfc_CFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) +- +-test_nfc_LDFLAGS = ++test_nfc_LDFLAGS = -pthread + test_nfc_LDADD = \ ++ $(top_builddir)/common/libhybris-common.la \ + $(top_builddir)/libnfc_nxp/libnfc_nxp.la \ + $(top_builddir)/hardware/libhardware.la + @@ -180,3 +203,10 @@ test_vibrator_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/vibrator/libvibrator.la @@ -15339,6 +28638,15 @@ +// vim:ts=4:sw=4:noexpandtab --- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/ui/ui.c +++ libhybris-0.1.0+git20151016+6d424c9/hybris/ui/ui.c +@@ -20,7 +20,7 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libui_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libui_compat_layer.so" + + HYBRIS_LIBRARY_INITIALIZE(ui, COMPAT_LIBRARY_PATH); + @@ -48,9 +48,11 @@ HYBRIS_IMPLEMENT_FUNCTION1(ui, uint32_t, struct graphic_buffer*); HYBRIS_IMPLEMENT_FUNCTION1(ui, void*, graphic_buffer_get_native_buffer, @@ -15351,6 +28659,17 @@ +#endif HYBRIS_IMPLEMENT_FUNCTION1(ui, int, graphic_buffer_init_check, struct graphic_buffer*); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/vibrator/vibrator.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/vibrator.c +@@ -22,7 +22,7 @@ + + #include + +-HYBRIS_LIBRARY_INITIALIZE(vibrator, "/system/lib/libhardware_legacy.so"); ++HYBRIS_LIBRARY_INITIALIZE(vibrator, "libhardware_legacy.so"); + + HYBRIS_IMPLEMENT_FUNCTION0(vibrator, int, vibrator_exists); + HYBRIS_IMPLEMENT_FUNCTION1(vibrator, int, vibrator_on, int); --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/hybris/wifi/Makefile.am @@ -0,0 +1,17 @@ @@ -15386,7 +28705,7 @@ +Cflags: -I${includedir} --- /dev/null +++ libhybris-0.1.0+git20151016+6d424c9/hybris/wifi/wifi.c -@@ -0,0 +1,51 @@ +@@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Canonical Ltd + * @@ -15411,7 +28730,7 @@ +#include +#include + -+#define COMPAT_LIBRARY_PATH "/system/lib/libhardware_legacy.so" ++#define COMPAT_LIBRARY_PATH "libhardware_legacy.so" + +HYBRIS_LIBRARY_INITIALIZE(wifi, COMPAT_LIBRARY_PATH); + @@ -15438,6 +28757,8 @@ +HYBRIS_IMPLEMENT_FUNCTION1(wifi, const char *, wifi_get_fw_path, int); +HYBRIS_IMPLEMENT_FUNCTION1(wifi, int, wifi_change_fw_path, const char *); +HYBRIS_IMPLEMENT_FUNCTION0(wifi, int, ensure_entropy_file_exists); ++HYBRIS_IMPLEMENT_FUNCTION4(wifi, int, wifi_send_driver_command, ++ char*, char*, char*, size_t); --- libhybris-0.1.0+git20151016+6d424c9.orig/utils/generate_wrapper_macros.py +++ libhybris-0.1.0+git20151016+6d424c9/utils/generate_wrapper_macros.py @@ -104,6 +104,12 @@ print """ @@ -15453,3 +28774,80 @@ """ for count in range(MAX_ARGS): +--- libhybris-0.1.0+git20151016+6d424c9.orig/utils/load_sym_files.py ++++ libhybris-0.1.0+git20151016+6d424c9/utils/load_sym_files.py +@@ -37,19 +37,22 @@ class LoadSymFiles(gdb.Command): + symdir = "/system/symbols" + libdir = "/system/lib" + +- if len(arg_list) == 1: ++ if len(arg_list) >= 1: + symdir = arg_list[0] ++ + if not os.path.isdir(symdir): +- print "error: invalid symbol directory(%s)"%symdir +- print "usage: load-sym-files [symbols-dir] [lib-dir]" ++ print("error: invalid symbol directory '%s'" % symdir) ++ print("usage: load-sym-files [symbols-dir] [lib-dir]") + return + + if len(arg_list) == 2: + libdir = arg_list[1] ++ + if not os.path.isdir(libdir): +- print "error: invalid library directory(%s)"%libdir +- print "usage: load-sym-files [symbols-dir] [lib-dir]" ++ print("error: invalid library directory '%s'" % libdir) ++ print("usage: load-sym-files [symbols-dir] [lib-dir]") + return ++ + try: + pid = gdb.selected_inferior().pid + except AttributeError: +@@ -59,34 +62,38 @@ class LoadSymFiles(gdb.Command): + if len(gdb.inferiors()) == 1: + pid = gdb.inferiors()[0].pid + else: +- print "error: no gdb support for more than 1 inferior" ++ print("error: no gdb support for more than 1 inferior") + return + + if pid == 0: +- print "error: debugee not started yet" ++ print("error: debugee not started yet") + return + + maps = open("/proc/%d/maps"%pid,"rb") + for line in maps: + # b7fc9000-b7fcf000 r-xp 00000000 08:01 1311443 /system/lib/liblog.so +- m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\s+r-xp.*(%s.*)"%libdir,line) ++ # m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\s+r-xp.*(%s.*)" % libdir, str(line)) ++ m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\sr-xp\s.*\s(.*)\\n", line.decode('ascii')) + if not m: + continue + +- start_addr = int(m.group(1),16) ++ start_addr = int(m.group(1), 16) + lib = m.group(2) + text_addr = 0 + +- p = subprocess.Popen("objdump -h "+lib , shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) +- for header in p.stdout.read().split("\n"): ++ if not lib.startswith(libdir): ++ continue ++ ++ p = subprocess.Popen("objdump -h " + lib , shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) ++ for header in p.stdout.read().decode('ascii').split("\n"): + #6 .text 00044ef7 00017f80 00017f80 00017f80 2**4 +- t = re.match("\s*[0-9]+\s+\.text\s+([0-9A-Fa-f]+\s+){3}([0-9A-Fa-f]+)",header) ++ t = re.match("\s*[0-9]+\s+\.text\s+([0-9A-Fa-f]+\s+){3}([0-9A-Fa-f]+)", header) + if t: + text_addr = int(t.group(2),16) + break ++ + symfile = symdir + lib + if os.path.isfile(symfile): + gdb.execute("add-symbol-file %s 0x%X" % (symfile, start_addr+text_addr)) + +- + LoadSymFiles() diff -Nru libhybris-0.1.0+git20151016+6d424c9/debian/rules libhybris-0.1.0+git20151016+6d424c9/debian/rules --- libhybris-0.1.0+git20151016+6d424c9/debian/rules 2016-04-21 09:07:32.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/rules 2016-08-05 16:46:15.000000000 +0000 @@ -77,21 +77,44 @@ | gzip >../$(PKG_source)_$(UPS_version).orig.tar.gz rm -rf $(PKG_source)-$(UPS_version) -override_dh_auto_configure: +ANDROID_HEADERS_PATH = /usr/include/android +DEFAULT_CONFIGURATION = \ + --enable-wayland \ + --with-android-headers=$(ANDROID_HEADERS_PATH) \ + --enable-property-cache +ARCH_CONFIGURATION = + ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), armhf)) - dh_auto_configure --sourcedirectory=hybris -- \ - --enable-wayland \ - --enable-arch=arm \ - --with-android-headers=/usr/include/android \ - --enable-mali-quirks \ - --enable-property-cache -else - dh_auto_configure --sourcedirectory=hybris -- \ - --enable-wayland \ - --enable-arch=x86 \ - --with-android-headers=/usr/include/android \ - --enable-property-cache +ARCH_CONFIGURATION = \ + --enable-arch=arm \ + --enable-mali-quirks \ + --enable-experimental +# We enable the linker selection overrides here as we want to stay +# with the jb linker on a range of selected production devices to +# not cause any extra risk for regressions on them. They will +# migrate to a newer linker version when ported to arm64. +ARCH_CONFIGURATION += \ + --enable-ubuntu-linker-overrides +endif +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), arm64)) +ARCH_CONFIGURATION = \ + --enable-arch=arm64 \ + --enable-mali-quirks \ + --enable-experimental endif +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), i386)) +ARCH_CONFIGURATION = \ + --enable-arch=x86 +endif +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), amd64)) +ARCH_CONFIGURATION = \ + --enable-arch=x86 +endif + +override_dh_auto_configure: + dh_auto_configure --sourcedirectory=hybris -- \ + $(DEFAULT_CONFIGURATION) \ + $(ARCH_CONFIGURATION) override_dh_install: # Fill in important variables