Бросок исключения C++ после встроенного-asm перехода

Я имею, некоторые нечетные сам изменяющий код, но в корне его являются довольно простой проблемой: Я хочу смочь выполнить a jmp (или a call) и затем от той произвольной точки выдают исключение и поймали его блоком попытки/выгоды, который содержал jmp/call.

Но когда я делаю это (в gcc 4.4.1 x86_64) результаты исключения в a terminate() поскольку это было бы, если исключение было выдано от за пределами попытки/выгоды. Я действительно не вижу, как это отличается, чем выдача исключения изнутри некоторой обширной библиотеки, все же это, очевидно - потому что это просто не работает.

Как я могу выполнить a jmp или call но все еще отбросьте исключение назад к исходной попытке/выгоде? Почему эта попытка/выгода не продолжает обрабатывать эти исключения, как она была бы, если функция обычно вызывалась?

Код:

#include <iostream>
#include <stdexcept>

using namespace std;

void thrower()
{
    cout << "Inside thrower" << endl;
    throw runtime_error("some exception");
}

int main()
{
    cout << "Top of main" << endl;  

    try {
        asm volatile (
            "jmp *%0" // same thing happens with a call instead of a jmp
            :
            : "r"((long)thrower)
            :
        );
    } catch (exception &e) {
        cout << "Caught : " << e.what() << endl;
    }
    cout << "Bottom of main" << endl << endl;
}

Ожидаемый вывод:

Top of main 
Inside thrower 
Caught : some exception
Bottom of main

Эффективная выходная мощность:

Top of main
Inside thrower
terminate called after throwing an instance of 'std::runtime_error'
  what():  some exception
Aborted
5
задан SoapBox 15 April 2010 в 02:30
поделиться

3 ответа

Вы смотрели на код сборки, сгенерированный gcc, если бы ваш блок try {} содержал просто вызов функции? Я почти уверен, что компилятор C++ делает больше, чем просто переход в этот момент, поскольку ему нужно иметь возможность отследить стек при возникновении исключения.

Ваш код может быть работоспособным, если вы сможете имитировать шаги, которые gcc предпринимает при структурировании вызова функции.

Обновление: этот вопрос может дать больше информации. В частности, может оказаться полезной часть Itanium ABI, касающаяся бросания и перехвата: link

1
ответ дан 14 December 2019 в 13:30
поделиться

Вы смотрели, как ваша реализация обрабатывает исключения? Он включает в себя поиск адресов компьютеров в таблицах, чтобы выяснить, что программа делала в конкретном месте, которое бросило, и что делали все вызывающие абоненты. По крайней мере, в Mac OS X GCC.

Единственная другая система, на которую я смотрел, Metrowerks Codewarrior для Mac (когда-то давно) использовала аналогичную систему, хотя и несколько более прозрачную. Компилятор может прозрачно вставлять функции для любого изменения контекста исключения.

Вы не молитесь о том, чтобы сделать это портативным.

3
ответ дан 14 December 2019 в 13:30
поделиться

После выполнения встроенной сборки вы получаете поведение, определяемое реализацией (7.4 / 1).

Вам следует попробовать настроить стековый фрейм; детали зависят от платформы, и я не знаю, как это сделать на x86_64.

1
ответ дан 14 December 2019 в 13:30
поделиться
Другие вопросы по тегам:

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