2013-07-25 3 views
3

Я пытаюсь получить границу для функции ядра (например, системные вызовы). Теперь, если я правильно понял, я могу получить начальный адрес интересующей функции, прочитав /proc/kallsyms или System.map, но я не знаю, как получить конечный адрес этой функции.Получить конечный адрес функции ядра Linux во время выполнения

Как вы знаете, /proc/kallsyms позволяет нам просматривать таблицу символов для ядра Linux, чтобы мы могли видеть начальный адрес всех экспортированных символов. Можно ли использовать начальный адрес следующей функции для вычисления конечного адреса предыдущей функции? Если мы не сможем сделать это, не могли бы вы предложить мне другие способы?

+0

Зачем вам нужно знать «конечный адрес» функции? –

+1

Мне нужно это знать, потому что я хочу сделать «функцию inlining» во время выполнения. После этого я могу построить Control Flow Graph, который включает в себя базовые блоки заинтересованной функции и всех ее вызываемых лиц. – user2571676

ответ

1

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

Вы можете попытаться найти начальный адрес следующей функции, но это не всегда будет работать. Представьте себе следующее:

void func_a() { 
    // do something 
} 

static void helper_function() { 
    // do something else 
} 

void func_b() { 
    // ... 
    helper_function(); 
    // ... 
} 

Вы можете получить адрес func_a и func_b, но helper_function не показывать вверх, потому что ничего не нужно ссылаться на него. Если вы попытались использовать func_b в качестве конца func_a (при условии, что порядок в скомпилированном коде эквивалентен порядку в исходном коде, что не гарантируется), вы попадете случайно, включая код, который вам не нужен включите - и, возможно, не найдете код, который вам нужно найти при встраивании других функций в func_b.

Итак, как мы находим эту информацию? Ну, если вы думаете об этом - информация есть существует - все пути в пределах func_a в конечном итоге заканчиваются (в цикле, возврате оператора, хвостовом вызове и т. Д.), Вероятно, до начала helper_function.

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

Последнее примечание: в этом примере у вас возникли бы проблемы с поиском helper_function, чтобы знать его встроенный, поскольку символ не будет отображаться в kallsyms. Решение состоит в том, что вы можете отслеживать инструкции call в отдельных функциях, чтобы определить, какие скрытые функции существуют, о которых вы не знали.

TL; DR: Вы можете найти только конечный адрес, проанализировав скомпилированный код. Вы все равно должны разбирать это, так что просто сделайте это один раз.

Смежные вопросы