Атрибут раздела GCC игнорируется в шаблонной функции - PullRequest
0 голосов
/ 04 января 2019

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

Кажется, что атрибут section GCC просто игнорируется при использовании в шаблонной функции / классе. Моя проблема звучит подобно тому, с чем столкнулся этот пользователь Тем не менее, я не вижу, что предложенное решение применимо к моему делу.

Я собрал очень простой пример, который демонстрирует это. Рассмотрим этот кусок кода:

void handler_func() { }

using handler_type = void(*)();

struct S { handler_type handler; };

template <typename T>
void templated()
{
    static S __attribute__((section(".templ_section"))) __attribute__((used)) templ_instance {handler_func};
}

void free()
{
    static S __attribute__((section(".free_section"))) __attribute__((used)) free_instance {handler_func};
}

struct Foo{};

int main(int argc, char** argv)
{
    templated<Foo>();

    free();
}

Я надеялся, что templ_instance будет помещен в .templ_section, а free_instance будет помещен в .free_section.

Однако, это расположение переменных с GCC:

0000000000000000 l     O .free_section  0000000000000008 _ZZ4freevE13free_instance
0000000000000000 l    d  .data.rel.local._ZZ9templatedI3FooEvvE14templ_instance 0000000000000000 .data.rel.local._ZZ9templatedI3FooEvvE14templ_instance
0000000000000000 u     O .data.rel.local._ZZ9templatedI3FooEvvE14templ_instance 0000000000000008 _ZZ9templatedI3FooEvvE14templ_instance

и вот что делает Clang:

0000000000000000 l     O .free_section  0000000000000008 _ZZ4freevE13free_instance
0000000000000000  w    O .templ_section 0000000000000008 _ZZ9templatedI3FooEvvE14templ_instance

Я не могу поверить, что это ожидаемое поведение в GCC. Есть ли способ обойти это?

1 Ответ

0 голосов
/ 04 января 2019

Если случается, что тип templ_instance не зависит от типа шаблона T, вы можете обойти это, имея этот объект в свободной функции:

S& templated_impl()
{
    static S __attribute__((section(".templ_section"))) __attribute__((used)) templ_instance {nullptr};
    return templ_instance;
}

template <typename T>
void templated()
{
    static S& templ_instance = templated_impl();
    templ_instance = { handler_func };
}

Живая демоверсия

GCC (8.x)

  .zero 8
  .section .free_section,"aw"
  .align 8
  .type free()::free_instance, @object
  .size free()::free_instance, 8
free()::free_instance:
  .quad handler_func()
  .section .templ_section,"aw"  // BINGO!
  .align 8
  .type templated_impl()::templ_instance, @object
  .size templated_impl()::templ_instance, 8
templated_impl()::templ_instance:

Clang (7.x)

  .size void templated<Foo>(), .Lfunc_end4-void templated<Foo>()
  .cfi_endproc
  .type templated_impl()::templ_instance,@object # @templated_impl()::templ_instance
  .section .templ_section,"aw",@progbits
  .p2align 3
templated_impl()::templ_instance:
  .quad handler_func()
  .size templated_impl()::templ_instance, 8

  .type free()::free_instance,@object # @free()::free_instance
  .section .free_section,"aw",@progbits
  .p2align 3
free()::free_instance:
...