Как восстанавливаются трассировки стека из дампа ядра?

Ваша проблема в том, что для запуска Firefox требуется некоторое время. Если вы запустите его в фоновом режиме, в следующий раз, когда вы сделаете firefox --new-tab, ваш первый экземпляр еще не запущен и не готов открыть другую вкладку. Вы должны подождать некоторое время после запуска первого экземпляра Firefox :

.
#!/bin/bash
while read line
do
    if pgrep -u $USER firefox > /dev/null
    then
        firefox --new-tab "$line" &
    else
        firefox "$line" &
        sleep 3                 # You may want to tune this value
    fi < /dev/null
done < /root/file

Остерегайтесь, что с такой конструкцией любая программа в вашем цикле может съесть то, что исходит от stdin, и это преждевременно завершит ваш цикл. Поэтому я превентивно добавил < /dev/nullв часть if.

1
26.09.2019, 00:00
1 ответ

Как вы правильно догадались, символы берутся из информации о символах, встроенной в файлы ELF. Некоторая информация о символах необходима для возможности динамического связывания, даже если полная таблица символов отсутствует.

Что касается фактической трассировки стека, то при вызове функции место, куда должен вернуться процессор, сохраняется. Для процессоров, таких как x86, он помещается в стек. Для машин RISC он обычно помещается в регистр.Если функция хочет вызвать какие-либо другие функции (, то есть это не leafфункция ), тогда этот регистр помещается в стек. Код stacktrace находит эти адреса в стеке, ищет ближайший адрес в символах, стоящих перед ним, и сообщает об этом. Некоторый код трассировки стека печатает как имя символа, так и его расстояние, что может дать вам больше уверенности в его точности. Например, если символ находится всего в 40 байтах перед адресом возврата, то гораздо больше уверенности в том, что он находится в этом коде, по сравнению с 40 000 байтами раньше. В последнем случае можно предположить, что адрес возврата указывает на другую функцию, но эта функция не имеет записи в таблице символов.

Многие вещи могут сделать это неточным. Если компилятор встраивает, скажем, функцию a в функцию b, то вы можете быть в функции a, но трассировка стека сообщит, что вы находитесь в b.

Если компилятор выполняет «оптимизацию хвостового вызова», где функция a заканчивается чем-то вроде return b();, а функция c вызывает функцию a, вы можете ожидать, что трассировка покажет c ->a ->b, но вы увидит только c ->b. Это может сбивать с толку, если вы посмотрите на исходный код c и увидите, что он никогда не вызывает b напрямую.

1
28.04.2021, 23:29

Теги

Похожие вопросы