Функция jni вызывает некоторую функцию libc, о которой gdb не знает - PullRequest
0 голосов
/ 04 июня 2019

У меня есть простая функция JNI, которую я использую для чтения данных из файла в byte[] из кода C UnixUtil.unsafeReadToByteArray, который реализован как:

JNIEXPORT jlong JNICALL Java_net_xxxxxxx_UnixUtil_unsafeReadToByteArray
  (JNIEnv *e, jclass jc, jint fd, jbyteArray array, jlong offset, jlong count){
  signed char *array_native_ptr = (*e) -> GetByteArrayElements(e, array, NULL);
  ssize_t bytes_read = read(fd, array_native_ptr + offset, (size_t) count);
  (*e) -> ReleaseByteArrayElements(e, array, array_native_ptr, 0);
  return bytes_read;
}

Профилирование Java-приложения, выполняющего функцию, обнаружилоськакой-то неясный результат.Вот вершина:

enter image description here

Одной из самых горячих вещей оказалась некая инструкция по адресу 0x18eb1f от libc-2.27.so.Я хотел понять, что это было, но GDB не знает об этом

(gdb) disas 0x18eb1f
No function contains specified address

Objdump'ing libc для grep адреса, я обнаружил, что

18eb0b:       72 0f                   jb     18eb1c <__nss_group_lookup@GLIBC_2.2.5+0x24ddc>
[...]
18eb1c:       48 89 d1                mov    %rdx,%rcx
18eb1f:       f3 a4                   rep movsb %ds:(%rsi),%es:(%rdi)

Что выглядит как часть__nss_group_lookup, в то время как __nss_group_lookup, кажется, не содержит адрес:

(gdb) disas __nss_group_lookup
Dump of assembler code for function __nss_passwd_lookup:
   0x0000000000169d40 <+0>:     mov    rax,QWORD PTR [rip+0x281121]        # 0x3eae68
   0x0000000000169d47 <+7>:     mov    DWORD PTR fs:[rax],0x26
   0x0000000000169d4e <+14>:    mov    eax,0xffffffff
   0x0000000000169d53 <+19>:    ret    
End of assembler dump. making the things more unclear then it was before.

, что делает вещи более неясными, чем раньше.

Вопрос: Можете ли вы дать какой-нибудь намек, где искать, чтобы понять, почему инструкция, принадлежащая __nss_group_lookup, самая горячая при вызове jni_GetByteArrayElements / jni_ReleaseByteArrayElements и что это на самом деле.

Я ожидалпоскольку jni_GetByteArrayElements / jni_ReleaseByteArrayElements копирует byte[] из кучи Java в кучу C через memcpy, это будет самый горячий вариант.

1 Ответ

2 голосов
/ 04 июня 2019

Очевидно, что libc в вашей системе не содержит символов отладки (в общей библиотеке нет раздела .symtab). Поэтому GDB показывает ближайший экспортированный символ из .dynsym, который не имеет ничего общего с самой горячей функцией.

rep movsb инструкция предполагает, что этот фрагмент является частью memcpy реализации.

Установите пакет libc-dbg (или как он называется в вашем дистрибутиве Linux).

например. на моем Ubuntu 18.04 адрес __nss_group_lookup+0x24ddc действительно указывает на memcpy внутренности:

(gdb) disas __nss_group_lookup+0x24ddc
Dump of assembler code for function __memmove_avx_unaligned_erms:
   0x00007ffffef7ead0 <+0>:     mov    %rdi,%rax
   ...
   0x00007ffffef7eb1c <+76>:    mov    %rdx,%rcx
   0x00007ffffef7eb1f <+79>:    rep movsb %ds:(%rsi),%es:(%rdi)
   0x00007ffffef7eb21 <+81>:    retq
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...