Throwing C ++ exception after inline-asm transition

I have an odd self-modifying code, but its root is quite a simple problem: I want to be able to execute jmp(or a call), and then throw an exception from this arbitrary point and hooked a try / catch block containing jmp/ call.

But when I do this (in gcc 4.4.1 x86_64), the exception results in terminate()as if this exception were thrown out of the scope of try / catch. I really don’t see how this differs from the fact that you selected an exception from some extensive library, but it is obvious that this just does not work.

How can I execute jmpor call, but still throw an exception for the original try / catch? Why doesn't this try / catch continue to handle these exceptions, as if the function was being called normally?

The code:

#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;
}

Expected Result:

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

Actual conclusion:

Top of main
Inside thrower
terminate called after throwing an instance of 'std::runtime_error'
  what():  some exception
Aborted
+5
source share
4 answers

If you are using gcc 4.4.7 (and higher) on x86-64 linux , using the dwarf exception handling mechanism (which may by default), I have a way to handle this.

Suppose your inline build code is a function inline_add. It will call another function addthat may throw an exception. Here is the code:

extern "C" int add(int a, int b) {
    throw "in add";
}

int inline_add(int a, int b) {
    int r = 0;
    __asm__ __volatile__ (
        "movl %1, %%edi\n\t"
        "movl %2, %%esi\n\t"
        "call add\n\t"
        "movl %%eax, %0\n\t"
        :"=r"(r)
        :"r"(a), "r"(b)
        :"%eax"
    );
    return r;
}

inline_add :

try {
    inline_add(1, 1);
} catch (...) {
    std::cout << "in catch" << std::endl;
}

, gcc inline_add. , . (. " C" )

, , gcc, ,

​​:

void build_exception_frame(bool b) {
    if (b) {
        throw 0;
    }
}

inline_add :

try {
    inline_add(1, 1);
    build_exception_frame(false);
} catch (...) {
    std::cout << "in catch" << std::endl;
}

.

build_exception_frame ,

, gcc, build_exception_frame, :

void build_exception_frame(bool b) __attribute__((optimize("O0")));

, gcc .

, gcc try/catch, , .

, gcc .

- , , , . .

+1

, ? , , , , , . , Mac OS X GCC.

, , Metrowerks Codewarrior Mac () , . .

.

+3

, gcc, try {} ? , ++ , , .

, , gcc .

: . , Itanium ABI:

+1

, , (7.4/1).

You should try to set the stack frame; the details are platform specific and I don't know how to do this on x86_64.

+1
source

All Articles