Динамическое перемещение раздела кода - PullRequest
12 голосов
/ 22 февраля 2010

Просто из любопытства интересно, можно ли переместить кусок кода во время выполнение программы. Например, у меня есть функция, и эта функция должна заменяться в памяти каждый раз после того, как он был выполнен. Одна идея, которая пришла нам в голову это использовать самоизменяющийся код, чтобы сделать это. Согласно некоторым интернет-ресурсам, самоизменяющийся код может быть выполнен в Linux, но все же я не уверен, возможно ли такое динамическое перемещение. Кто-нибудь сталкивался с этим?

Ответы [ 3 ]

8 голосов
/ 22 февраля 2010

Да, динамическое перемещение определенно возможно. Однако вы должны убедиться, что код полностью автономен или что он обращается к глобальным / внешним функциям по абсолютным ссылкам. Если ваш код может быть полностью независимым от позиции, то есть единственные ссылки, которые он делает, относятся к самому себе, значит, все готово. В противном случае вам нужно будет сделать исправления самостоятельно во время загрузки.

С GCC вы можете использовать -fpic для генерации кода, независимого от позиции. Передача -q или --emit-relocs компоновщику заставит его передавать информацию о перемещении. Спецификация ELF (ссылка в формате PDF) содержит информацию о том, как использовать эту информацию о перемещении; если вы не используете ELF, вам нужно найти соответствующую документацию для вашего формата.

3 голосов
/ 23 февраля 2010

Как говорит Карл, это можно сделать, но вы открываете банку с червями. На практике единственные люди, которые пытаются это сделать, - это ученые или авторы вредоносных программ (теперь надевающий пламяустойчивый плащ).

Вы можете скопировать некоторый код в область кучи malloc, а затем вызвать его с помощью указателей функций, но в зависимости от ОС может потребоваться включить выполнение в сегменте. Вы можете попытаться скопировать некоторый код в сегмент кода (стараясь не перезаписать следующую функцию), но ОС, вероятно, сделала этот сегмент доступным только для чтения. Возможно, вы захотите взглянуть на ядро ​​Linux и посмотреть, как оно загружает свои модули.

0 голосов
/ 22 февраля 2010

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

...