C МАКРОС для сравнения имен функций с предопределенным списком имен

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

Я имел в виду примерно следующее:

#define SHOULD_CHECK_STOP_MONITOR           (1 == Configuration.dwShouldMonitor)
#define MY_CHECK_MACRO(f) (if(SHOULD_CHECK_STOP_MONITOR && /* What do I do here? */))

void MyHookedFunctionName_A(...)
{
    if(!MY_CHECK_MACRO(__FUNCTION__))
        goto lbl_Cleanup;

    /* rest of code logic */

lbl_Cleanup:
    return ...;
}

void MyHookedFunctionName_B(...)
{
    if(!MY_CHECK_MACRO(__FUNCTION__))
        goto lbl_Cleanup;

    /* rest of code logic */

lbl_Cleanup:
    return ...;
}

Результат, которого я хочу достичь, - это предварительно скомпилированная логика, которая должна выполняться не в динамической среде выполнения, а при компиляции. где, если 1 == Configuration.dwShouldMonitor настроен на True, он проверит остальную логику, где у меня будет какой-то предопределенный список имен функций ["MyHookedFunctionName_A", "MyHookedFunctionName_C", "MyHookedFunctionName_D"], и макрос будет знать, возвращать ли False или True на основе имени функции. Таким образом, в этом примере MyHookedFunctionName_B будет выполняться, а MyHookedFunctionName_A - нет из-за предопределенного списка при компиляции.

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

edit 2019.09.15: я добавляю сюда то, что мне хотелось бы получить после логики предварительной компиляции

void MyHookedFunctionName_A(...)
{
    if(!(1 == Configuration.dwShouldMonitor && False))
        goto lbl_Cleanup;
...
}

void MyHookedFunctionName_B(...)
{
    if(!(1 == Configuration.dwShouldMonitor && True))
        goto lbl_Cleanup;
...
}

Где True или False были сгенерированы во время компиляции на основе имен строк функций


person 0xAK    schedule 15.09.2019    source источник
comment
Я не думаю, что это возможно с макросом. Если бы это был C ++, вы могли бы использовать constexpr функцию ...   -  person HolyBlackCat    schedule 15.09.2019
comment
@HolyBlackCat, А альтернативного эквивалента в C нет? Единственный вариант, который у меня есть, - выполнять эту логику внутри каждой функции во время выполнения?   -  person 0xAK    schedule 15.09.2019
comment
Я не могу ни о чем думать, но могу ошибаться.   -  person HolyBlackCat    schedule 15.09.2019
comment
Результатом вызова макроса является текст, обычно текст программы C или C ++. Совершенно не ясно, какой текст вы хотите сгенерировать. Можете ли вы опубликовать текст, который вы хотите сгенерировать, когда установлен флаг, и какой-то текст, который вы хотите сгенерировать из того же источника, когда флаг не установлен? Вам не нужно публиковать исходный код перед предварительной обработкой. Именно то, что вы хотите увидеть после предварительной обработки.   -  person n. 1.8e9-where's-my-share m.    schedule 15.09.2019
comment
эй @nm, я добавил ожидаемый результат на основе имен строк функций, я хочу, чтобы он удобно создавал операторы True или False, которые я легко контролирую для всех моих функций, без необходимости в этой логике, чтобы быть выполняется динамически   -  person 0xAK    schedule 15.09.2019
comment
Я нашел эту статью на сайте GNU. Они дают пример того же самого, чего вы стремитесь достичь. Преобразование аргумента макроса в символьную константу, чтобы его можно было вычислить. Похоже, это можно сделать, но не во время компиляции. gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing   -  person mreff555    schedule 15.09.2019


Ответы (1)


Многие компиляторы должны иметь возможность полностью оптимизировать вашу проверку во время выполнения.

Вот простая программа, чтобы проиллюстрировать это.

#include <string.h>
#include <stdio.h>

static const char* func_list[] = { "foo", "bar" };

static inline int is_in_list(const char* f) {
    for (int i = 0; i < sizeof(func_list)/sizeof(func_list[0]); ++i)
        if (strcmp(f, func_list[i]) == 0)
            return 1;
    return 0;
}

#define HOOKME if (SHOULD_HOOK && is_in_list(__func__)) return;

void foo() {
    HOOKME;
    printf("foo\n");
}
void bar() {
    HOOKME;
    printf("bar\n");
}
void baz() {
    HOOKME;
    printf("baz\n");
}

int main()
{
    foo();
    bar();
    baz();
}

Скомпилируйте его с -DSHOULD_HOOK = 1 и -O2, и хороший компилятор, вероятно, заставит foo и bar исчезнуть.

foo:
  ret
bar:
  ret
.LC0:
  .string "baz"
baz:
  mov edi, OFFSET FLAT:.LC0
  jmp puts
main:
  sub rsp, 8
  xor eax, eax
  call baz
  xor eax, eax
  add rsp, 8
  ret

Не все компиляторы умеют это делать. Выбирайте инструменты с умом. Демо.

person n. 1.8e9-where's-my-share m.    schedule 15.09.2019
comment
Похоже на то, что я ищу, но не могу заставить его работать, есть идеи, должен ли он работать с Microsoft Visual Studio 2015 компилятором? - person 0xAK; 15.09.2019
comment
@ 0xAK Этот конкретный код не работает (т.е. MSC не оптимизирует его). - person n. 1.8e9-where's-my-share m.; 15.09.2019