C - вызов функции через func_ptr, почему она не работает? - PullRequest
5 голосов
/ 19 июня 2011

У меня есть следующий код:

void print(const char* str){
      system_call(4,1,str,strlen(str)); }

void foo2(void){ print("goo \n");}


void buz(void){ ...}

int main(){
char buf[256];
    void (*func_ptr)(void)=(void(*)(void))buf;
    memcpy(buf,foo2, ((void*)buz)-((void*)foo2));
    func_ptr();
    return 0;
}

вопрос в том, почему этот код упадет?

ответ был: что-то в вызове функции не через указатель относится к относительному адресу, но я не смог выяснить, что здесь не так? какая линия проблемная?

спасибо за вашу помощь

Ответы [ 3 ]

3 голосов
/ 19 июня 2011

Ну, для начала, нет ничего, что говорит о том, что foo2 () и buz () должны быть рядом друг с другом в памяти.А для другого, как вы предполагаете, код должен быть относительным, чтобы такие трюки работали.Но, прежде всего, это не разрешено стандартом.

Как упоминал Крис Лутс, переменные стека (авто) не выполняются во многих операционных системах для защиты от атак.

2 голосов
/ 19 июня 2011

Первые две строки в вашей функции main () проблематичны.

Строка 1. (void(*)(void))buf преобразование буфера в указатель на функцию не определено

Строка 2. ((void*)buz)-((void*)foo2) вычитание указателей не определено, если указатели не указывают в пределах одного массива.

Кроме того, Section 5.8 Functions из H&S говорит: «Хотя указатель на функцию часто считается адресом кода функции в памяти, на некоторых компьютерах указатель функции фактически указывает на блок информации, необходимый для вызова функция. "

1 голос
/ 19 июня 2011

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

Я не вижу преимущества / смысла в попытке скопировать код из одного места в другое. Как прокомментировали некоторые, нелегко определить количество кода относительности / перераспределения в функции C.

Вы попытались скопировать код функции в область памяти данных. Некоторые микроконтроллеры просто сказали бы: «Отпусти!». На машинных архитектурах, которые имеют память, разделенную данными / программами, при наличии очень понимающего компилятора (или компилятора, который распознает данные / модификаторы / атрибуты кода), он будет компилироваться в конкретные инструкции перемещения кода-данных. Это работает, но это работает ... Однако даже в арках памяти, разделенных данными / кодами, выполнение команд памяти данных невозможно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...