Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed37aca9 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Find first non-zero jit debug entry.

Sometimes a process will have multiple shared libraries loaded
that have defined __jit_debug_descriptor. Specifically, art testing
will load libart.so and libartd.so, which would have broken unwinding
through jit'd code for art testing if libart.so winds up being found first.
In order to avoid duplicating the code for the linker to figure out
which one is live, change the algorithm to find the first non-zero
first_entry_ set in __jit_debug_descriptor.

Bug: 68396769

Test: Passes unit tests.
Test: Verified this can unwind 137-cfi on arm/arm64.
Change-Id: Ic4d403065d2c6f22476ef0171e7add17cd1464cd
parent 85d0c3ad
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ cc_test {
    data: [
        "tests/files/elf32.xz",
        "tests/files/elf64.xz",
        "tests/files/offline/jit_debug_arm32/*",
        "tests/files/offline/jit_debug_x86_32/*",
        "tests/files/offline/gnu_debugdata_arm32/*",
        "tests/files/offline/straddle_arm32/*",
+6 −8
Original line number Diff line number Diff line
@@ -173,7 +173,6 @@ void JitDebug::Init(Maps* maps) {
  initialized_ = true;

  std::string descriptor_name("__jit_debug_descriptor");
  uint64_t descriptor_addr = 0;
  for (MapInfo* info : *maps) {
    if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
      continue;
@@ -194,17 +193,16 @@ void JitDebug::Init(Maps* maps) {
    }

    Elf* elf = info->GetElf(memory_, true);
    uint64_t descriptor_addr;
    if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr)) {
      // Search for the first non-zero entry.
      descriptor_addr += info->start;
      entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr);
      if (entry_addr_ != 0) {
        break;
      }
    }

  if (descriptor_addr == 0) {
    return;
  }

  entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr);
}

Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
+32 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class JitDebugTest : public ::testing::Test {
                       "a000-c000 --xp 00000000 00:00 0\n"
                       "c000-f000 rwxp 00000000 00:00 0\n"
                       "f000-11000 r-xp 00000000 00:00 0\n"
                       "12000-14000 r-xp 00000000 00:00 0\n"
                       "100000-110000 rw-p 0000000 00:00 0\n"
                       "200000-210000 rw-p 0000000 00:00 0\n"));
    ASSERT_TRUE(maps_->Parse());
@@ -72,6 +73,16 @@ class JitDebugTest : public ::testing::Test {
    elf->FakeSetInterface(interface);
    interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
    map_info->elf = elf;

    map_info = maps_->Get(6);
    ASSERT_TRUE(map_info != nullptr);
    elf_memories_.push_back(new MemoryFake);
    elf = new ElfFake(elf_memories_.back());
    elf->FakeSetValid(true);
    interface = new ElfInterfaceFake(elf_memories_.back());
    elf->FakeSetInterface(interface);
    interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
    map_info->elf = elf;
  }

  template <typename EhdrType, typename ShdrType>
@@ -293,6 +304,27 @@ TEST_F(JitDebugTest, get_elf_32) {
  EXPECT_EQ(elf, elf2);
}

TEST_F(JitDebugTest, get_multiple_jit_debug_descriptors_valid) {
  CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
  CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2000, 0x300);

  WriteDescriptor32(0xf800, 0x200000);
  WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
  WriteDescriptor32(0x12800, 0x201000);
  WriteEntry32Pad(0x201000, 0, 0, 0x5000, 0x1000);

  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr);
  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) == nullptr);

  // Now clear the descriptor entry for the first one.
  WriteDescriptor32(0xf800, 0);
  jit_debug_.reset(new JitDebug(process_memory_));
  jit_debug_->SetArch(ARCH_ARM);

  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr);
  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) != nullptr);
}

TEST_F(JitDebugTest, get_elf_x86) {
  CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);

+219 −0
Original line number Diff line number Diff line
@@ -406,4 +406,223 @@ TEST(UnwindOfflineTest, jit_debug_x86_32) {
      frame_info);
}

TEST(UnwindOfflineTest, jit_debug_arm32) {
  std::string dir(TestGetFileDirectory() + "offline/jit_debug_arm32/");

  MemoryOfflineParts* memory = new MemoryOfflineParts;
  AddMemory(dir + "descriptor.data", memory);
  AddMemory(dir + "descriptor1.data", memory);
  AddMemory(dir + "stack.data", memory);
  for (size_t i = 0; i < 7; i++) {
    AddMemory(dir + "entry" + std::to_string(i) + ".data", memory);
    AddMemory(dir + "jit" + std::to_string(i) + ".data", memory);
  }

  FILE* fp = fopen((dir + "regs.txt").c_str(), "r");
  ASSERT_TRUE(fp != nullptr);
  RegsArm regs;
  uint64_t reg_value;
  ASSERT_EQ(1, fscanf(fp, "r0: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R0] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r1: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R1] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r2: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R2] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r3: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R3] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r4: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R4] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r5: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R5] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r6: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R6] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r7: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R7] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r8: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R8] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r9: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R9] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r10: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R10] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "r11: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R11] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "ip: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_R12] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "sp: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_SP] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "lr: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_LR] = reg_value;
  ASSERT_EQ(1, fscanf(fp, "pc: %" SCNx64 "\n", &reg_value));
  regs[ARM_REG_PC] = reg_value;
  regs.SetFromRaw();
  fclose(fp);

  fp = fopen((dir + "maps.txt").c_str(), "r");
  ASSERT_TRUE(fp != nullptr);
  // The file is guaranteed to be less than 4096 bytes.
  std::vector<char> buffer(4096);
  ASSERT_NE(0U, fread(buffer.data(), 1, buffer.size(), fp));
  fclose(fp);

  BufferMaps maps(buffer.data());
  ASSERT_TRUE(maps.Parse());

  ASSERT_EQ(ARCH_ARM, regs.Arch());

  std::shared_ptr<Memory> process_memory(memory);

  char* cwd = getcwd(nullptr, 0);
  ASSERT_EQ(0, chdir(dir.c_str()));
  JitDebug jit_debug(process_memory);
  Unwinder unwinder(128, &maps, &regs, process_memory);
  unwinder.SetJitDebug(&jit_debug, regs.Arch());
  unwinder.Unwind();
  ASSERT_EQ(0, chdir(cwd));
  free(cwd);

  std::string frame_info(DumpFrames(unwinder));
  ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
  EXPECT_EQ(
      "  #00 pc 00018a5e  libarttestd.so (Java_Main_unwindInProcess+865)\n"
      "  #01 pc 0000212d (offset 0x2000)  137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
      "boolean)+92)\n"
      "  #02 pc 00011cb1  anonymous:e2796000 (boolean Main.bar(boolean)+72)\n"
      "  #03 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #04 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
      "  #05 pc 000bf7a9  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
      "  #06 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #07 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #08 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #09 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #10 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #11 pc 00011c31  anonymous:e2796000 (int Main.compare(Main, Main)+64)\n"
      "  #12 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #13 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
      "  #14 pc 000bf7a9  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
      "  #15 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #16 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #17 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #18 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #19 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #20 pc 00011b77  anonymous:e2796000 (int Main.compare(java.lang.Object, "
      "java.lang.Object)+118)\n"
      "  #21 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #22 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
      "  #23 pc 000bf7a9  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
      "  #24 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #25 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #26 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #27 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #28 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #29 pc 00011a29  anonymous:e2796000 (int "
      "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
      "java.util.Comparator)+304)\n"
      "  #30 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #31 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)\n"
      "  #32 pc 000bf7bb  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
      "  #33 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #34 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #35 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #36 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #37 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #38 pc 0001139b  anonymous:e2796000 (boolean Main.foo()+178)\n"
      "  #39 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #40 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
      "  #41 pc 000bf7a9  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
      "  #42 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #43 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #44 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #45 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #46 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #47 pc 00010aa7  anonymous:e2796000 (void Main.runPrimary()+70)\n"
      "  #48 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #49 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
      "  #50 pc 000bf7a9  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
      "  #51 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #52 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #53 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #54 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #55 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #56 pc 0000ba99  anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n"
      "  #57 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #58 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)\n"
      "  #59 pc 000bf7bb  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
      "  #60 pc 00247833  libartd.so "
      "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
      "11ShadowFrameEtPNS_6JValueE+382)\n"
      "  #61 pc 0022e935  libartd.so "
      "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
      "6JValueEb+244)\n"
      "  #62 pc 0022f71d  libartd.so "
      "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
      "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
      "  #63 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
      "  #64 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
      "  #65 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
      "  #66 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)\n"
      "  #67 pc 000bf7bb  libartd.so "
      "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
      "  #68 pc 003b292d  libartd.so "
      "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_"
      "8ArgArrayEPNS_6JValueEPKc+52)\n"
      "  #69 pc 003b26c3  libartd.so "
      "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_"
      "jmethodIDSt9__va_list+210)\n"
      "  #70 pc 00308411  libartd.so "
      "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+76)\n"
      "  #71 pc 000e6a9f  libartd.so "
      "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDSt9__va_listNS_"
      "9Primitive4TypeENS_10InvokeTypeE+1486)\n"
      "  #72 pc 000e19b9  libartd.so "
      "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+40)\n"
      "  #73 pc 0000159f  dalvikvm32 "
      "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+30)\n"
      "  #74 pc 00001349  dalvikvm32 (main+896)\n"
      "  #75 pc 000850c9  libc.so\n",
      frame_info);
}

}  // namespace unwindstack
+22.1 KiB

File added.

No diff preview for this file type.

Loading