Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimized DEX repair alternative method #22

Closed
anestisb opened this issue Sep 6, 2016 · 4 comments
Closed

Optimized DEX repair alternative method #22

anestisb opened this issue Sep 6, 2016 · 4 comments
Assignees

Comments

@anestisb
Copy link
Owner

anestisb commented Sep 6, 2016

This project is heavily relying to SmaliEx (baksmali/smali wrapper) in order to de-optimize bytecode targets (APKs/JARs) that we want extract from factory system images as part of the vendor proprietary blobs.

While this approach was relatively working until now, it heavily depends into smali & smaliEx maintainers being always up to speed with all recent ART runtime changes (#20, #18). Unfortunately this is practically not the case since teams need a decent amount of time to adjust to Google changes. Plust we need to do a lot of porting / glueing work to upgrade script to match these changes. Considering how often such changes happen in the Android ecosystem, I was looking for an alternative workaround.

Back in Feb 2015 that I've upstreamed oatdump++ to AOSP (https://android-review.googlesource.com/#/c/134380/), I've pushed a DEX export functionality to dump bytecode from .rodata section of the OAT file. Of course the exported DEX bytecode is not the actual original since the DEX-to-DEX transformations have already been applied (https://github.com/anestisb/oatdump_plus#dex-to-dex-optimisations).

However, to my great surprise when I was researching some other aspects of the dex2oat compiler backends, I've noticed that current implementation front-end is not aborting when DEX-to-DEX transformations have been partially or fully applied already to input. Instead the compiler overrides them when it's not happy with the VTABLE indexes. This makes more sense if someone considers the ART profiling functionality where pre-optimized code maybe need to be recompiled without having the original DEX.

This effectively means that the bytecode we want to repair from /system partition can be extracted with oatdump host tool, re-inserted back to APK/JAR and re-compile (pre-optimize) when building from AOSP.

Theoretically dex2oat can happen either at host (pre-optimize) or directly at target when first boot. Until we're confident that this approach works for all bytecode we want to repair for supported devices, we choose to always pre-optimize so potential errors can be spotted as early as possible.

The execution flow of the repairs is:

  1. oatdump to dump bytecode from OAT ELF
  2. dexrepair (https://github.com/anestisb/dexRepair) to repair DEX CRC checksum
  3. Rename bytecode to match naming conventions (classes.dex, classes2.dex, etc.)
  4. jar to append bytecode back to source APK/JAR
  • zipalign & resign steps are handled automatically from AOSP build chain.

This new method is a work in progress and still needs lots of testing, however so far results (manual repair bytecode samples for N5x target) seems quite promising.

@anestisb anestisb self-assigned this Sep 6, 2016
anestisb added a commit that referenced this issue Sep 6, 2016
More info at #22

Signed-off-by: Anestis Bechtsoudis <[email protected]>
@anestisb
Copy link
Owner Author

anestisb commented Sep 7, 2016

Undocumented dex2oat --abort-on-hard-verifier-error (https://android.googlesource.com/platform/build/+/android-7.0.0_r4/core/dex_preopt_libart.mk#111) flag is causing issues with some APKs when pre-compiled at host level. Removing that flag and comparing oatdump from original ODEX and regenerated ODEX doesn't reveal any issues of code flow differences.

Looking for alternatives to circumvent this without modifying AOSP makefile.

anestisb added a commit that referenced this issue Sep 7, 2016
Mitigate issue #22 (comment)

This effectively means that we instruct the build to not optimize
the repaired bytecode, just zipalign & resign them. As such the
bytecode will be optimized at device first boot. This was the only
option to circumvent "--abort-on-hard-verifier-error" without
modifying the AOSP default makefiles.

Signed-off-by: Anestis Bechtsoudis <[email protected]>
@anestisb
Copy link
Owner Author

anestisb commented Sep 7, 2016

AOSP compilation is successfully completed for supported targets. Now testing images against supported devices to ensure that repaired bytecode is working as expected.

@anestisb
Copy link
Owner Author

Added support for OS X after building platform/art targeting MAC host tools. Since current Nougat upstream has broken MAC host support at this commit, a small edit had to be introduced to allow oatdump to work under MAC host:

anestisb@blackbird:[art]: git diff
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 72c0cea..c6a833e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -141,7 +141,7 @@ OatFileBase* OatFileBase::OpenOatFile(const std::string& elf_filename,
                                       std::string* error_msg) {
   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));

-  ret->PreLoad();
+  // ret->PreLoad();

   if (!ret->Load(elf_filename,
                  oat_file_begin,

@anestisb
Copy link
Owner Author

No issues so far after testing for couple of days with N5x & N6p Nougat builds. Mark as good to go until further notice.

Joshndroid added a commit to Joshndroid/android-prepare-vendor that referenced this issue Sep 15, 2016
* Manual system deopt disable

Nougat support for bytecode deoptimization & repair is broken.
This commit is a temporarily (hopefully) solution to override the
default enabled deoptimization so that the rest of execution chain
of the script can be debugged / developed against other compatibility
issues with Nougat AOSP tags.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Reorder proprietary blobs merged list

Ensure that /vendor entries are placed before /system entries

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Log messages edits

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Individual targets for shared libraries

More info at anestisb#21

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* [WIP] Prepare base for alternative repair method

Since de-optimization and repair via smali/basmali is broken
we seek alternative methods via ART oat utils. The idea is to start
dumping DEX from OAT rodata section, repair the checksum and
let the dex2oat do the offset recalculation work again when pre-opt
for AOSP build. Have partially being test and not sure that it works
across the border. We'll just give it a shot.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x blobs list update

Some apps under system partition have been moved from
/app to /priv-app

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x remove 'libgps.utils' shared libs

Module is now available from AOSP source:
https://android.googlesource.com/platform/hardware/qcom/gps/+/android-7.0.0_r1/msm8994/utils/Android.mk#53

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x remove libloc_api_v02

Module is currently available from AOSP Nougat branches

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Bytecode whitelist common for all repair methods

Speed-up logic that skips repairing unnecessary bytecode is common
for all supported methods. The OATDUMP method is still WIP to ensure
it can work for supported devices.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x remove libloc_ds_api

Module is currently available from AOSP Nougat branches

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x API-24 remove libloc_eng

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Vendor shared libraries have priority

It has been noticed that AOSP defines some target modules
for shared libraries that are present in vendor partition blobs.

e.g.
build/core/base_rules.mk:183: *** vendor/htc/flounder: MODULE.TARGET.SHARED_LIBRARIES.libbt-vendor_32 already defined by hardware/broadcom/libbt.
build/core/ninja.mk:163: recipe for target 'out_userdebug_Linux_7.0.0_r1/sources/build-aosp_flounder.ninja' failed

As such for generated shared libraries modules that are
located under vendor partition ensure that they always
selected by using the LOCAL_OVERRIDES_PACKAGES
flag.

We need to investigate if that is desired for /system too
so that we can simplify some bits that are quite complex
for some devices (e.g. gps location libs for N5x).

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix extension extract bug

When image was provided with "../" path
the extension was wrongly extracted.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Overrides not working as expected

We still can't avoid conflicting module names. As such
we can't blindly add an individual module target for all
shared libraries. We have to proceed with cherry picking.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Cherrypick individual modules shared libs

Continuing the effort to fix [1], it seems that we can't blindly
upgrade all shared libraries from PRODUCT_COPY_FILES
to individual modules. Most of the supported devices conflict
in multiple places for re-definitions. While most case can be
dealt with some override options some can't.

As such we have to proceed with shared libs cherrypicking
to indicate which libraries from the master blobs list should
be defined as a separate module.

For this purpose the generate-vendor script is taking an
additional argument with a txt file which contains such libs
for each target device. File templates are located under
devices root dir (same with proprietary blobs list) and will
be periodically be updated with the required dependencies.

First target is support for N5x.

[1] anestisb#21

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Revert "N5x blobs list update"

This reverts commit 358cff7.

* Typo in repair method type

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Update hostTools dir structure

Since we need to also push some lib shared objects
refactor dir structure to match bin / lib64 convention
that AOSP host tools expect.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* More N5x shared libs

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x remove lights.bullhead blob

Module is available in AOSP under:
device/lge/bullhead/liblight

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p blobs list update

Some location shared libs are now available from AOSP
"device/huawei/angler/location"

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Enable LOCAL_DEX_PREOPT for /system bytecode

Allow repaired bytecode from /system partition to be pre-optimized
if global DEX_PREOPT flag is set.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* OATDUMP byte code repair method

More info at anestisb#22

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Update hostTools binaries

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p shared libs for API-24

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Disable shared libs module gen when no modules

Don't try generating module targets for shared libraries when
shared blobs list file is empty.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x shared libs list update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix undefined variable bug

If not shared libraries modules are selected for a
provided partition, PKGS array is not defined resulting
to a runtime error. Add a boolean flag to ensure that array
is iterated only when elements available.

We probably need to re-consider the way we want to use
dynamically appended arrays in bash to avoid such cases,
although for the time being leave it for a later clean-up.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove old signatures from repaired JARs/APKs

In Nougat release Google introduced a new APK signature format V2 [1].
Since some bits from repaired APKs might collide (whole thing seems to be
on a transition state at the moment) remove old signatures to ensure that build
chains picks-up a fresh copy to re-sign.

[1] https://source.android.com/security/apksigning/v2.html

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Variable rename

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Don't try to repair boot jars

So far none of the Nexus devices has a boot framework jar
that is not available from AOSP. As such, save up-time by
skipping them when iterating the byte code locations, since
boot jars will never be selected from proprietary blob lists
with the current status of Nexus devices.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Push oatdump Linux bin

We're still missing the lib64 deps build from AOSP host
targets. We need to isolate the ones required to run
oatdump tool and push only those, avoiding polluting the
repo with unnecessary libraries.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove debug code

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Quiet JAR/APK signature deletion

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix boot jars name blacklist bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove some verbose log messages

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove special skip for resource only JARs

Some framework jars have only resource data and no bytecode.
So far we were explicitly skipping them by name. Follow-up bytecode
detection logic is smart enough to identify such cases and skip them
automatically.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Script help message rename

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Log message update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Relative paths for log messages

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Shellcheck lint fixes

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Never DEX preopt repaired APKs/JARs

Mitigate issue anestisb#22 (comment)

This effectively means that we instruct the build to not optimize
the repaired bytecode, just zipalign & resign them. As such the
bytecode will be optimized at device first boot. This was the only
option to circumvent "--abort-on-hard-verifier-error" without
modifying the AOSP default makefiles.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix Linux bin dir structure bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Merge .gitignore files to simplify maintenance

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Out of channel oatdump bin deps download

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* chmod txt list files

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Low memory size warning

Fixes issue anestisb#13

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Typo

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Revert "N5x remove lights.bullhead blob"

This reverts commit d233bc4.

* Revert "Revert "N5x remove lights.bullhead blob""

This reverts commit f45d1ba.

* Revert "N5x remove libloc_api_v02"

This reverts commit 14beaf5.

* Revert N5x libloc_ds_api

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Update README

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Update README

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Sort proprietary blob list files

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Edit comments & log messages

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Re-enable LOCAL_OVERRIDES_PACKAGES

Individual shared libs targets from prebuilt should use that
flag to override potential AOSP definitions of same modules

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x libloc_api_v02 cannot build from AOSP

We've satisfied the shared libraries dependencies, although
we're still missing the header includes. Try to override the
AOSP module with our own prebuilt.

```
device/lge/bullhead/location/loc_api/loc_api_v02/location_service_v02.h:78:10: fatal error: 'qmi_idl_lib.h' file not found
#include "qmi_idl_lib.h"
```

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove LOCAL_OVERRIDES_PACKAGES

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p update blob lists

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x update blob lists

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Additional BoardConfigVendor.mk flags

Since we might need to control some vendor board config flags
without editing the AOSP sources, expose an additional txt
configuration file from generate-vendor.sh script. All flags specified
in '--flags-list' file will be appended to generated 'BoardConfigVendor.mk'

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Revert missing blobs for N5x / N6p

Since we fixed the missing dependencies issues by
effectively closing the AOSP QCOM location partial
sources, revert the required prebuilt shared libraries.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Typo fixes

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* README update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* More README updates

Configuration files explained + more examples

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Enable LOCAL_PROPRIETARY_MODULE

When individual library is located under /vendor set the
LOCAL_PROPRIETARY_MODULE, otherwise it will
be stored in the default /system out base.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Split bytecode files from master blobs list

In order to have better & easier control over the bytecode
archive files that we want to repair from factory & include,
separate them from the master blobs list file.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Optimize whitelist skips

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Optimize configuration files logic

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Typo fix

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p update configuration files

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Preserve all when cp unmodified APK/JAR

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p blobs list update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Revert accidentally removed inner blacklist

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Shellcheck lint fixes

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* drop root support

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Allow MAC OS with 7z

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* OS X compatibility fixes

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Quiet 7z extract

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* fdisk unnecessary to check

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* 7z verify minimum support version

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix arg passing bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix empty vendor config list file bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove 7z special output directory

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix size calculation bug from du output

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Unnecessary escape bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Replace readlink with sh-realpath

Since OS X doesn't have by default GNU readlink, avoid an
aliasing nightmare for greadlink brew/macports by providing
a self-contained implementation of realpath. Thanks to mkropat
for the implementation.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Replace 7z with fuse-ext2

7z wasn't respecting symbolic links and was breaking
part of the following vendor generation logic that was
relying into them being untouched. It has been replaced
with fuse-ext2. Cheers to @jduck for pointing it out.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* umount / fusermount wrapping support

OSXFuse works with umount, while Linux FUSE works with
fusermount. Wrap around command based on HOST_OS

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Remove local rsync copy

Improve speed by mounting fuse-ext2 directly to
expected mountpoint without performing a local
rsync copy from image file.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Extra modules config file

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Beautify makefile

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Replace mv with symlink

Since mount points are RO, just create a symbolic
link from original /system to repaired /system when
not repairing have been applied.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix ln out dir bug when no repair

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Directory clean-up

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Refactor java version check

Also only enable check when repairing bytecode
with oat2dex.jar method.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* oatdump bytecode repair method for MAC

Push link with oatdump bin & deps zip compiled for OS X.

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Place configs under separate dir

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix OS X oatdump missing DYLD bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p extra modules config typo

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* grep out comments from proprietary-blobs.txt

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix JAVA_HOME set bug for MAC

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix empty configs parsing bug

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* README update examples

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p API-24 blobs config update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* umount if previous run with -k for same target

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N6p blobs config update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x/N6p enable dm-verity for /vendor

Fix for issue anestisb#25

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Update README

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Print error log if fust-ext2 fails

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* N5x config blobs update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Error handling bug fix

FACTORY_IMGS_DATA was unbound if very early
abort occurred (e.g. help screen or invalid arg).

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Fix issue anestisb#28

anestisb#28
Signed-off-by: Anestis Bechtsoudis <[email protected]>

* README update with FAQ

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Comments update & typo

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Check for non supported /vendor/priv-app repair

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Improve fuse mount error check

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* README changelog update

Signed-off-by: Anestis Bechtsoudis <[email protected]>

* Missing path normalization

Fixes issue anestisb#27

Signed-off-by: Anestis Bechtsoudis <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant