Определите уникальную и глобальную метку / символ сборки внутри функций C - PullRequest
0 голосов
/ 10 октября 2018

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

Пример:

// my build system will pass -DMYFILE_ID for each file, here I am trying to create a unique literal for each inline instance of the function
#define UN(X) #X
#define UNIQUE(X,Y) UN(X##Y)

void my_func(void)
{
    _asm("GLOBAL_LABEL_"UNIQUE(MYFILE_ID,__LINE__)":\n\t")
    my_c_code_I_want_to_track();
}

И что бы яхотел бы иметь в конце, находится в файле карты выходных символов компоновщика, что-то вроде этого

0xsome_address GLOBAL_LABEL_12_1
0xdifferent_address GLOBAL_LABEL_12_2
0xyeanotheraddress GLOBAL_LABEL_13_1

, что в принципе должно дать мне представление о том, по каким адресам был создан экземпляр my_c_code_i_want_to_track

Вся идеяв некотором роде вдохновлен тем, что метки в сборке на самом деле являются «символами», которые имеют размещение, и поэтому их адреса можно проверить, но они фактически не занимают свое собственное пространство.

Проблемы: 1. Возможно ли вообщечтобы метки сборки были определены следующим образом 2. Как заставить эти метки остаться и появиться в файле карты выходных символов 3. Итакчто-то не так с макросом UNIQUE, так как я получаю "переопределение метки" при попытке компиляции

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Вы можете использовать %= (например, label%=:) внутри Extended- asm шаблона , чтобы заставить компилятор генерировать уникальное число, чтобы избежать конфликтов имен, когда функция, содержащая inline-asm,несколько раз вставляется в одну единицу компиляции.

#define STRINGIFY(x) #x
#define STR(x) STRINGIFY(x)
int foo(int x) {
    asm("marker" __FILE__ "_line" STR(__LINE__)  "_uniqueid%=:" :::);
    return x+1;
}


int caller1(int x) {
    return foo(x);
}

int caller2(int x) {
    return foo(x);
}

компилируется в следующий asm с gcc -O3 ( на Godbolt ):

foo(int):
        marker/tmp/compiler-explorer-compiler11899-55-1ki0cth.pehm/example.cpp_line4_uniqueid7:
        lea     eax, [rdi+1]
        ret
caller1(int):
        marker/tmp/compiler-explorer-compiler11899-55-1ki0cth.pehm/example.cpp_line4_uniqueid22:
        lea     eax, [rdi+1]
        ret
caller2(int):
        marker/tmp/compiler-explorer-compiler11899-55-1ki0cth.pehm/example.cpp_line4_uniqueid41:
        lea     eax, [rdi+3]
        ret

Это, конечно, выигралне собирается, потому что / не является допустимым символом метки в GAS.

Используя MYFILE_ID, который содержит только символы, которые могут появиться в именах символов, это будет прекрасно работать, и вы должны иметь возможностьпросмотреть все метки marker на выходе nm.

0 голосов
/ 10 октября 2018

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

__attribute__((noinline))

Также обратите внимание, что вам нужно пометить символ как глобальный.Давайте выделим это в макрос, чтобы мы могли хорошо отформатировать, не меняя значения __LINE__:

#define MAKE_LABEL \
    __asm__( \
        "GLOBAL_LABEL_" UNIQUE(MYFILE_ID, __LINE__) ":" \
        "\n\t.global GLOBAL_LABEL_" UNIQUE(MYFILE_ID, __LINE__) \
    )

Но расширение макроса отключено.К сожалению, я не могу объяснить вам, почему это работает.Но вот правильное определение макроса:

#define UN(X) #X
#define UNIQUE2(X,Y) UN(X##Y)
#define UNIQUE(X,Y) UNIQUE2(X,Y)

В противном случае вы получите __LINE__ вместо, скажем, 23.

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