Изменение имени MSVC C ++ из строки во время выполнения - PullRequest
0 голосов
/ 14 марта 2019

Сначала я начну с причины, по которой мне нужно искажать имена во время выполнения.

Мне нужно создать мост между dll и ее оболочкой

namespace Wrapper
{
    class  __declspec(dllexport) Token
    {
    public:

        virtual void release() {}
    };
}

class  __declspec(dllexport) Token
{
public:

    virtual void release(){}
};

Идея состоит в том, чтобы использовать dumpin длясгенерировать все искаженные имена токенов класса, содержащих dll, и затем разобрать их.

? release @ Token @@ UAEXXZ -> void Token :: release (void)

после этого я хочуконвертировать - это соответствовать Wrapper, поэтому мне нужно изменить имя функции

void Token :: release (void) -> void Wrapper :: Token :: release (void)

а затем мне нужно изменить его снова, чтобы я мог создать файл def, который направляет старую функцию на новую.

? release @ Token @@ UAEXXZ =? release @ Token @ Wrapper @@ UAEXXZ

весь этот процесс должен быть запущен во время выполнения.

Первое и самое простое решение - найти функцию, которая искажает строки, но я не смог найти ...

любойдругое решение?

Ответы [ 2 ]

2 голосов
/ 14 марта 2019

Компилятор Clang совместим с ABI с MSVC, включая искажение имен.Базовая инфраструктура является частью проекта LLVM, и я обнаружил llvm-undname , который разбивает имена MSVC.Возможно, вы можете переделать его, чтобы добавить пространство имен Wrapper:: к символам и изменить его.

Вы можете найти вдохновение для искажения имен в этом тестовом коде .

0 голосов
/ 14 марта 2019

Если вам разрешено изменять DLL, я бы обычно использовал другой подход, экспортируя функцию извлечения extern "C" (которая не искажает, следовательно, не требует разборки) и используя виртуальный интерфейс для доступа к классу (обратите внимание, что виртуальный интерфейс не должен быть dllexported тогда).Ваш интерфейс Token в любом случае кажется виртуальным.

Что-то в этом духе (не проверено, просто чтобы показать идею):

Заголовок доступа к DLL:

class Token  // notice no dllexport!
{
protected:
    // should not be used to delete directly (DLL vs EXE heap issues)
    virtual ~Token() {}
    virtual void destroyImpl() = 0; // pure virtual
public:
    static inline void destroy(Token* token) {
        // need to check for NULL otherwise virtual call would segfault
        if (token) token->destroyImpl();
    }
    virtual void doSomething() = 0; // pure virtual
};

extern "C" __declspec(dllexport) Token * createToken();

DLLреализация:

class TokenImpl: public Token
{
public:
    virtual void destroyImpl() {
        delete this;
    }
    virtual void doSomething() {
        // implement here
    }
};

extern "C" __declspec(dllexport) Token * createToken()
{
    return new TokenImpl;
}

Использование:

// ideally wrap in RAII to be sure to always release
// (e.g. can use std::shared_ptr with custom deleter)
Token * token = createToken();

// use the token
token->doSomething();

// destroy
Token::destroy(token);

С помощью shared :: ptr (также можно создать встроенную функцию создания удобства typedef / static в интерфейсе Token):

std::shared_ptr<Token> token(createToken(),
                             // Use the custom destroy function
                             &Token::destroy);
token->doSomething()
// token->destroy() called automatically when last shared ptr reference removed

Таким образом, вам нужно только экспортировать функцию создателя extern-C (и функцию release, если не часть интерфейса), которая затем не будет искажена, поэтому ее будет легко использовать через загрузку во время выполнения.

...