GDB strace показывает, что пытается выполнить поиск по неверному адресу - PullRequest
6 голосов
/ 10 марта 2012

Я столкнулся с такой ошибкой при выполнении команды ni во время отладки gdb:

Внимание:
Невозможно вставить точку останова 0.
Ошибка доступа к адресу памяти 0x3ac706a: Ошибка ввода / вывода.

0xf6fa4771 в siglongjmp () из /lib/libc.so.6

Чтобы выяснить, с какой проблемой сталкивается GDB, я связываю GDB и получаю такой вывод:

rt_sigprocmask (SIG_BLOCK, NULL, [RT_1], 8) = 0
ptrace (PTRACE_PEEKTEXT, 651, 0xcc4fdf60, [0x1cc4fe470]) = 0
ptrace (PTRACE_PEEKTEXT, 651, 0xcc4fe480, [0x3ac706a4506fa1d]) = 0
rt_sigprocmask (SIG_BLOCK, NULL, [RT_1], 8) = 0
...
...
rt_sigprocmask (SIG_BLOCK, NULL, [RT_1], 8) = 0
rt_sigprocmask (SIG_BLOCK, NULL, [RT_1], 8) = 0
ptrace (PTRACE_GETREGS, 27781, 0, 0x7fff8990e8b0) = 0
ptrace (PTRACE_PEEKTEXT, 27781, 0x3ac7068, [0x28b]) = -1 EIO (ошибка ввода / вывода)
ptrace (PTRACE_PEEKTEXT, 27781, 0x3ac7068, [0x28b]) = -1 EIO (ошибка ввода / вывода)

Это означает, что GDB сначала ptrace по адресу памяти 0xcc4fe480 и получает значение 0x3ac706a4506fa1d (на самом деле это 8-байтовое значение 0x03ac706a4506fa1d ). Позже он получает выровненный адрес 0x3ac7068 из первых 4 байтов этого значения, что является недопустимым адресом и приводит к невозможности трассировки gdb.

Содержимое / proc / [pid] / maps:

cbce2000-cc353000 r-xp 00000000 08:03 295479 xxx.so
cc353000-cc3f0000 r - p 00670000 08:03 295479 xxx.so
cc3f0000-cc3f6000 rw-p 0070d000 08:03 295479 xxx.so
cc3f6000-cc3fe000 rw-p cc3f6000 00:00 0
cc3fe000-cc3ff000 --- p cc3fe000 00:00 0
cc3ff000-cc4ff000 rwxp cc3ff000 00:00 0
cc4ff000-cc500000 --- p cc4ff000 00:00 0

cc500000-cc600000 rwxp cc500000 00:00 0
cc62d000-cc673000 r-xp 00000000 08:03 295545 гг.со
cc673000-cc674000 --- p 00046000 08:03 295545 гг.со
cc674000-cc675000 r - p 00046000 08:03 295545 гг.со
cc675000-cc676000 rw-p 00047000 08:03 295545 ггг.со

Показывает, что адрес 0xcc4fe480 из раздела, выделенного жирным шрифтом выше. Этот раздел не относится ни к какому .so или bin-файлу.

Этот вопрос фактически связан с другим вопросом http://stackoverflow.com/questions/9564417/gdb-cant-insert-internal-breakpoint,, который еще не решен. Я обнаружил эти проблемы во время расследования предыдущего выпуска.

У меня есть 3 вопроса здесь:
1. Посмотрите на вывод strace для ptrace здесь:
ptrace (PTRACE_PEEKTEXT, 651, 0xcc4fe480, [0x3ac706a4506fa1d]) = 0
Почему последний параметр аннотирован квадратными скобками? Означает ли это, что оно представляет возвращаемое значение? На странице руководства написано, что ptrace должен возвращать слово read для PTRACE_PEEKTEXT, но, похоже, что вывод strace не следует этому, поэтому я подозреваю, что он показывает возвращаемое значение в последнем параметре.
2. Есть раздел (который жирным шрифтом) между двумя .so, но не связанный ни с одним inode. Что представляет собой такой раздел?
3. Gdb читает одно слово из этого раздела и использует это слово в качестве адреса, но на самом деле это неверный адрес. Каковы возможные причины такой ошибки?

Спасибо!

Ответы [ 2 ]

5 голосов
/ 12 марта 2012
  1. Посмотрите на вывод strace для ptrace здесь: ptrace (PTRACE_PEEKTEXT, 651, 0xcc4fe480, [0x3ac706a4506fa1d]) = 0 Почему последний параметр аннотируется квадратными скобками?Означает ли это, что оно представляет возвращаемое значение?

Правильно.

  1. Есть раздел (который с жирным шрифтом) между двумя., Но несвязан с любым индексом.Что представляет собой такой раздел?

Это область памяти, которая была mmap отредактирована с флагом MAP_ANONYMOUNS (то есть она не соответствует ни одному файлу на диске).

Поскольку размер этой области составляет ровно 1 МБ, и поскольку он окружен частными областями, отображенными с помощью PROT_NONE, можно с уверенностью предположить, что эта область представляет собой некоторый стек потоков, окруженный защитными зонами стека.

  1. Gdb читает одно слово из этого раздела и использует это слово в качестве адреса, но на самом деле это неверный адрес.Каковы возможные причины такой ошибки?

По какой-то причине GDB считает, что должен быть код по адресу 0x3ac7068, и хочет разместить внутреннюю точку остановатам.GDB использует внутренние точки останова для отслеживания загруженных разделяемых библиотек (между прочим).

Вывод maintenance info break должен показать, какой код, по мнению GDB, находится по «плохому» адресу.

0 голосов
/ 10 марта 2012

Я предполагаю, что ваш код переполнен и записывается по действительному адресу, и GDB обращается к той области памяти, ожидая адрес, но получая ненужные данные. Какой раздел кода вы пытаетесь отладить? Это может помочь нам.

...