Можем ли мы хранить инструкции в динамически выделенной памяти на языке Си? - PullRequest
5 голосов
/ 02 ноября 2011

Хорошо известно, что мы можем хранить DATA в динамически выделенной памяти.

Однако мне было интересно, сможем ли мы хранить NEW INSTRUCTIONS или NEW FUNCTIONS в куче? Какие-нибудь реальные приложения?

Подготовка к собеседованию, поэтому, пожалуйста, потерпите меня, если это не разумный вопрос.

Ответы [ 5 ]

8 голосов
/ 02 ноября 2011

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

Однако, если мы добавим сведения о деталях реализации и ОС (таблицы перемещений, защита страниц и т. Д.), То да, это возможно. Например, пользовательские динамические загрузчики кода (которые не используют предоставляемую ОС загрузку DLL / SO) работают следующим образом.

8 голосов
/ 02 ноября 2011

Да, конечно.Как вы думаете, компилятор "точно в срок" ?Некоторые атаки с разбиванием стека работают по схожему принципу (выполнение кода в стеке, а не в куче).Это одна из причин, по которой современные операционные системы имеют защиту от выполнения страниц «данных».(Законные генераторы динамического кода должны были бы отключить такую ​​защиту.) См. Также статью в Википедии о самомодифицирующемся коде .

1 голос
/ 02 ноября 2011

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

Здесь - это пример сохранения инструкции BSWAP x86 в виде данных в массиве (не динамически распределяемой, но, как правило, это не имеет значения) и ее выполнения. На самом деле в этом примере в качестве данных хранится не одна инструкция BSWAP, а полная подпрограмма, вызываемая на языке C, которая придерживается предписанного компилятором соглашения о вызовах, определяющего, как в него передаются параметры и из него возвращаются возвращаемые значения.

Примером является 32-разрядное приложение Windows, и поскольку оно предназначено для работы в Windows, оно также должно гарантировать, что область, содержащая инструкции, помечена как читаемая и исполняемая (первая предоставляется тем, что они находятся в массив, который может быть прочитан и записан, и последнее обеспечивается вызовом функции VirtualProtect (), чтобы сообщить ОС пометить регион как исполняемый, что необходимо, поскольку ОС пытается защитить нас от случайного выполнения вредоносного кода (например, ненадежные данные, поступающие из Интернета)).

1 голос
/ 02 ноября 2011

Когда программа загружается в память, она в основном организована в три области памяти, называемые сегментами:

  • текстовый сегмент
  • сегмент стека
  • сегмент кучи

В текстовом сегменте (также называемом сегментом кода) находится скомпилированный код самой программы. Поскольку «НОВЫЕ ИНСТРУКЦИИ» или «НОВЫЕ ФУНКЦИИ» должны быть известны во время компиляции, поэтому мы не можем сохранить их в Heap.

Надеюсь, это поможет ответить на ваш запрос.

0 голосов
/ 02 ноября 2011

В общем смысле ответ: Нет ; потому что инструкции кода должны быть известны во время компиляции.

динамически связанные библиотеки могут быть более близкими, чтобы быть либеральными.

...