Author: Kazuki Sakamoto
Date: 2023-06-20T15:00:09-07:00
New Revision: b0b9605a544dbf26940a48777af401a419f4e4f1

URL: 
https://github.com/llvm/llvm-project/commit/b0b9605a544dbf26940a48777af401a419f4e4f1
DIFF: 
https://github.com/llvm/llvm-project/commit/b0b9605a544dbf26940a48777af401a419f4e4f1.diff

LOG: [lldb][ObjectFileELF] Set ModuleSpec file offset and size

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

ObjectFileELF::GetModuleSpecifications will load a .so file, which is page
aligned and uncompressed, directly from a zip file. However it does not
set the .so file offset and size to the ModuleSpec. Also crc32 calculation
uses more data than the .so file size.

Set the .so file offset and size to the ModuleSpec, and set the size to
MapFileData length argument. For normal file, file_offset should be zero,
and length should be the size of the file.

Differential Revision: https://reviews.llvm.org/D152757

Added: 
    lldb/unittests/ObjectFile/ELF/Inputs/liboffset-test.so
    lldb/unittests/ObjectFile/ELF/Inputs/offset-test.bin

Modified: 
    lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/unittests/ObjectFile/ELF/CMakeLists.txt
    lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp 
b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 82171dee221ec..727c1fa96af64 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -555,6 +555,14 @@ size_t ObjectFileELF::GetModuleSpecifications(
     if (header.Parse(data, &header_offset)) {
       if (data_sp) {
         ModuleSpec spec(file);
+        // In Android API level 23 and above, bionic dynamic linker is able to
+        // load .so file directly from zip file. In that case, .so file is
+        // page aligned and uncompressed, and this module spec should retain 
the
+        // .so file offset and file size to pass through the information from
+        // lldb-server to LLDB. For normal file, file_offset should be 0,
+        // length should be the size of the file.
+        spec.SetObjectOffset(file_offset);
+        spec.SetObjectSize(length);
 
         const uint32_t sub_type = subTypeFromElfHeader(header);
         spec.GetArchitecture().SetArchitecture(
@@ -586,8 +594,12 @@ size_t ObjectFileELF::GetModuleSpecifications(
                       __FUNCTION__, file.GetPath().c_str());
           }
 
+          // When ELF file does not contain GNU build ID, the later code will
+          // calculate CRC32 with this data_sp file_offset and length. It is
+          // important for Android zip .so file, which is a slice of a file,
+          // to not access the outside of the file slice range.
           if (data_sp->GetByteSize() < length)
-            data_sp = MapFileData(file, -1, file_offset);
+            data_sp = MapFileData(file, length, file_offset);
           if (data_sp)
             data.SetData(data_sp);
           // In case there is header extension in the section #0, the header we

diff  --git a/lldb/unittests/ObjectFile/ELF/CMakeLists.txt 
b/lldb/unittests/ObjectFile/ELF/CMakeLists.txt
index 4c59ca109a57e..68a78bab543c1 100644
--- a/lldb/unittests/ObjectFile/ELF/CMakeLists.txt
+++ b/lldb/unittests/ObjectFile/ELF/CMakeLists.txt
@@ -11,5 +11,7 @@ add_lldb_unittest(ObjectFileELFTests
 
 set(test_inputs
   early-section-headers.so
+  liboffset-test.so
+  offset-test.bin
   )
 add_unittest_inputs(ObjectFileELFTests "${test_inputs}")

diff  --git a/lldb/unittests/ObjectFile/ELF/Inputs/liboffset-test.so 
b/lldb/unittests/ObjectFile/ELF/Inputs/liboffset-test.so
new file mode 100644
index 0000000000000..3aa98db24991f
Binary files /dev/null and 
b/lldb/unittests/ObjectFile/ELF/Inputs/liboffset-test.so 
diff er

diff  --git a/lldb/unittests/ObjectFile/ELF/Inputs/offset-test.bin 
b/lldb/unittests/ObjectFile/ELF/Inputs/offset-test.bin
new file mode 100644
index 0000000000000..7de9ecf091e72
Binary files /dev/null and 
b/lldb/unittests/ObjectFile/ELF/Inputs/offset-test.bin 
diff er

diff  --git a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp 
b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
index 0381870f4e0a5..80abc5b80f84d 100644
--- a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
+++ b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
@@ -156,6 +156,39 @@ TEST_F(ObjectFileELFTest, 
GetModuleSpecifications_EarlySectionHeaders) {
   EXPECT_EQ(Spec.GetUUID(), Uuid);
 }
 
+TEST_F(ObjectFileELFTest, GetModuleSpecifications_OffsetSizeWithNormalFile) {
+  std::string SO = GetInputFilePath("liboffset-test.so");
+  ModuleSpecList Specs;
+  ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 0, 0, 
Specs));
+  ModuleSpec Spec;
+  ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ;
+  UUID Uuid;
+  Uuid.SetFromStringRef("7D6E4738");
+  EXPECT_EQ(Spec.GetUUID(), Uuid);
+  EXPECT_EQ(Spec.GetObjectOffset(), 0UL);
+  EXPECT_EQ(Spec.GetObjectSize(), 3600UL);
+  EXPECT_EQ(FileSystem::Instance().GetByteSize(FileSpec(SO)), 3600UL);
+}
+
+TEST_F(ObjectFileELFTest, GetModuleSpecifications_OffsetSizeWithOffsetFile) {
+  // The contents of offset-test.bin are
+  // -    0-1023: \0
+  // - 1024-4623: liboffset-test.so (offset: 1024, size: 3600, CRC32: 7D6E4738)
+  // - 4624-4639: \0
+  std::string SO = GetInputFilePath("offset-test.bin");
+  ModuleSpecList Specs;
+  ASSERT_EQ(
+      1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 1024, 3600, 
Specs));
+  ModuleSpec Spec;
+  ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ;
+  UUID Uuid;
+  Uuid.SetFromStringRef("7D6E4738");
+  EXPECT_EQ(Spec.GetUUID(), Uuid);
+  EXPECT_EQ(Spec.GetObjectOffset(), 1024UL);
+  EXPECT_EQ(Spec.GetObjectSize(), 3600UL);
+  EXPECT_EQ(FileSystem::Instance().GetByteSize(FileSpec(SO)), 4640UL);
+}
+
 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmThumbAddressClass) {
   /*
   // nosym-entrypoint-arm-thumb.s


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to