This is an archive of the discontinued LLVM Phabricator instance.

[lldb][Android] Support zip .so file
ClosedPublic

Authored by splhack on Jun 12 2023, 4:54 PM.

Details

Summary

In Android API level 23 and above, dynamic loader is able to load .so file
directly from APK, which is zip file.
https://android.googlesource.com/platform/bionic/+/master/
android-changes-for-ndk-developers.md#
opening-shared-libraries-directly-from-an-apk

The .so file is page aligned and uncompressed, so
ObjectFileELF::GetModuleSpecifications works with .so file offset and size
directly from zip file without extracting it. (D152757)

GDBRemoteCommunicationServerCommon::GetModuleInfo returns a module spec to LLDB
with "zip_path!/so_path" file spec, which is passed through from Android
dynamic loader, and the .so file offset and size.

PlatformAndroid::DownloadModuleSlice uses 'shell dd' to download the .so file
slice from the zip file with the .so file offset and size.

Depends on D152757

AndroidPlatformTest is added in D152855

Diff Detail

Event Timeline

splhack created this revision.Jun 12 2023, 4:54 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 12 2023, 4:54 PM
splhack published this revision for review.Jun 12 2023, 5:01 PM
splhack added reviewers: clayborg, labath, lanza, srhines.
Herald added a project: Restricted Project. · View Herald TranscriptJun 12 2023, 5:02 PM

This is definitely useful to support, I had a few comments mostly about matching lldb's coding style.

Also, are you running clang-format on your patches? There are a few places where I'm not sure if the formatting is right.

lldb/source/Host/CMakeLists.txt
110–122

I don't think this is correct to do. lldbHost is different than other libraries in that it's meant to provide functionality that lldb and lldb-server needs to work on the host system. Unconditionally adding a host subdirectory for android even when we're on Linux doesn't make sense to do.

lldb/source/Host/android/HostInfoAndroid.cpp
107 ↗(On Diff #530715)

You can avoid using std::string here (and invoking the constructor) by using an llvm::StringLiteral. Like so:

static constexpr llvm::StringLiteral k_zip_separator("!/");
108 ↗(On Diff #530715)

It's not obvious what the type of path is, please write out the type instead of using auto.

119–126 ↗(On Diff #530715)

It's not obvious what the types of these are (except for zip_file_spec), please write out the types explicitly.

126 ↗(On Diff #530715)

It's not obvious what 0 is as the parameter here, please make it look something like this:
/* offset = */ 0);

lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
257–260

Maybe it would be a good idea to centralize the run-as logic somewhere, right now it's pretty ad-hoc.

lldb/unittests/Host/CMakeLists.txt
42

Why not just match on "Android"?

splhack edited the summary of this revision. (Show Details)Jun 13 2023, 3:46 PM

@bulbazord thanks for reviewing! will address the types, formats.

lldb/source/Host/CMakeLists.txt
110–122

I agree with that, however, I think this is pretty much only way to unblock writing and running unit tests for the Android host system, which has been no tests at all. The AndroidPlatformTest D152855 requires this to run the tests on Linux, and Android is basically Linux, so, hope it still makes sense for the unit testing capability. (only android/LibcGlue.cpp is not buildable for Linux target.)

lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
257–260

Will look into these run-as things with D152494 centralize and if plugin.platform.android.platform-run-as possible.

lldb/unittests/Host/CMakeLists.txt
42

The reason is, as commented above, to run AndroidPlatformTest D152855 on Linux.

bulbazord added inline comments.Jun 13 2023, 4:44 PM
lldb/source/Host/CMakeLists.txt
110–122

I see. You want to be able to run the android host tests but that's not easy to do right now. I think this is a reasonable thing to want to do (especially since so much of android support in lldb is not well tested AFAIK).

Instead of making this functionality specific to android hosts, why not make it possible to do on all platforms? This would do a few things:

  • It would make it easier to test on more than just Linux and Android machines.
  • It would open up the possibility of being able to use an apk on the host machine instead of needing to fetch it from the remote device via adb shell dd. An optimization for sure, but for large shared objects this may be able to improve performance.

What do you think?

lldb/source/Host/android/ZipFile.cpp
1 ↗(On Diff #530715)

BTW, I haven't looked at this file too closely yet, but I think a better candidate for its location would be lldbUtility. It doesn't rely on anything else from lldb other than something else in lldbUtility.

splhack added inline comments.Jun 13 2023, 7:01 PM
lldb/source/Host/CMakeLists.txt
110–122

Yeah, sounds great to me! will update move things around.

  • include/lldb/Utility/ZipFile.h
  • source/Utility/ZipFile.cpp
  • HostInfoAndroid::ResolveZipPath -> ZipFile::ResolveBionicZipPath (this is bionic libc specific)
splhack updated this revision to Diff 531195.Jun 13 2023, 11:24 PM
  • ZipFile: zip file parser in Utility
    • include/lldb/Utility/ZipFile.h
    • source/Utility/ZipFile.cpp
  • ZipFileResolver: bionic zip .so file resolver, depends on Host::FileSystem
    • include/lldb/Host/common/ZipFileResolver.h
    • source/Host/common/ZipFileResolver.cpp
  • ZipFileResolverTest
    • unittests/Host/common
splhack added inline comments.Jun 14 2023, 9:36 AM
lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
257–260

run-as is centralized in D152933

splhack updated this revision to Diff 531394.Jun 14 2023, 9:45 AM

remove 'Depends on' from commit message.

splhack updated this revision to Diff 531576.Jun 14 2023, 5:05 PM

Fixed diff dependencies in order to fix CI
https://reviews.llvm.org/B238937

bulbazord accepted this revision.Jun 15 2023, 1:39 PM

Thanks for reworking it! You may want to wait a little bit before landing so others have some time to look over it, but I don't see anything that should prevent this from going in.

This revision is now accepted and ready to land.Jun 15 2023, 1:39 PM
mib added a subscriber: mib.Jun 15 2023, 1:56 PM
mib added inline comments.
lldb/include/lldb/Host/common/ZipFileResolver.h
31

This function name sounds like the the bionic linker is in the zip file which is not the case IIUC. I'm fine with adding a zip file resolver in lldb but I'd prefer if it had a generic name, otherwise, this should be a plugin.

lldb/source/Utility/ZipFile.cpp
20–22

Did you just copy & past the this file from somewhere else of did you implement it yourself ?

mib added inline comments.Jun 15 2023, 1:57 PM
lldb/include/lldb/Host/common/ZipFileResolver.h
31

what about this instead ?

splhack added inline comments.Jun 15 2023, 2:18 PM
lldb/include/lldb/Host/common/ZipFileResolver.h
31

Yes, should be good. will update this diff.

(Why it had "Bionic" because I thought the path encoding "zip_path!/lib_path" is bionic specific.)

lldb/source/Utility/ZipFile.cpp
20–22

I implemented this code.

logic

  • Linear search the end of central directory record from the file end because it is located at the end of the file with comment (64KB max)
  • Linear search the file from the central directory records that is pointed by the end of central directory record.
  • Get the file offset and size from the local file header that is pointed by the central directory record
  • Use unaligned_uint16_t/unaligned_uint32_t since Zip header is 1 byte aligned.
clayborg added inline comments.Jun 15 2023, 4:15 PM
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
1336

might be good to init this to an invalid value in case code changes over time?

splhack updated this revision to Diff 531969.Jun 15 2023, 7:08 PM

Rename ResolveBionicPath to ResolveSharedLibraryPath.

splhack added inline comments.Jun 15 2023, 7:41 PM
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
1336

yup, sounds good. will add with assert.

splhack updated this revision to Diff 531974.Jun 15 2023, 7:43 PM

Added eFileKindInvalid with assert

This revision was automatically updated to reflect the committed changes.

ResolveSharedLibraryPathWithZipExisting and ResolveSharedLibraryPathWithZipMissing are failing on Windows. Looking into.
https://lab.llvm.org/buildbot/#/builders/219/builds/3674

Fixed Windows test failures in D153390