Как посчитать статический инициализатор в файле ELF?

Я пытаюсь посчитать статические инициализаторы в файле C ++.

У меня уже есть решение (которое раньше работало с gcc-4.4), которое рассматривает размер ELF-секции .ctors.

После обновления до gcc-4.6 это, похоже, больше не возвращает действительных результатов (вычисленное количество статических инициализаторов равно 0, что не соответствует действительности, например, как возвращено nm).

Теперь проблема в том, что я бы хотел, чтобы решение работало даже в отсутствие символов (иначе я бы использовал nm).

Ниже приведен вывод readelf -SW примера исполняемого файла:

Существует 35 заголовков секций, начиная со смещения 0x4f39820:

Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .interp           PROGBITS        00000174 000174 000013 00   A  0   0  1
[ 2] .note.ABI-tag     NOTE            00000188 000188 000020 00   A  0   0  4
[ 3] .note.gnu.build-id NOTE            000001a8 0001a8 000024 00   A  0   0  4
[ 4] .gnu.hash         GNU_HASH        000001cc 0001cc 000918 04   A  5   0  4
[ 5] .dynsym           DYNSYM          00000ae4 000ae4 00a5e0 10   A  6   1  4
[ 6] .dynstr           STRTAB          0000b0c4 00b0c4 00ef72 00   A  0   0  1
[ 7] .gnu.version      VERSYM          0001a036 01a036 0014bc 02   A  5   0  2
[ 8] .gnu.version_r    VERNEED         0001b4f4 01b4f4 000450 00   A  6  13  4
[ 9] .rel.dyn          REL             0001b944 01b944 268480 08   A  5   0  4
[10] .rel.plt          REL             00283dc4 283dc4 0048c8 08   A  5  12  4
[11] .init             PROGBITS        0028868c 28868c 00002e 00  AX  0   0  4
[12] .plt              PROGBITS        002886c0 2886c0 0091a0 04  AX  0   0 16
[13] .text             PROGBITS        00291860 291860 3ac5638 00  AX  0   0 16
[14] malloc_hook       PROGBITS        03d56ea0 3d56ea0 00075a 00  AX  0   0 16
[15] google_malloc     PROGBITS        03d57600 3d57600 008997 00  AX  0   0 16
[16] .fini             PROGBITS        03d5ff98 3d5ff98 00001a 00  AX  0   0  4
[17] .rodata           PROGBITS        03d5ffc0 3d5ffc0 ffa640 00   A  0   0 64
[18] .eh_frame_hdr     PROGBITS        04d5a600 4d5a600 0004b4 00   A  0   0  4
[19] .eh_frame         PROGBITS        04d5aab4 4d5aab4 001cb8 00   A  0   0  4
[20] .gcc_except_table PROGBITS        04d5c76c 4d5c76c 0003ab 00   A  0   0  4
[21] .tbss             NOBITS          04d5df0c 4d5cf0c 000014 00 WAT  0   0  4
[22] .init_array       INIT_ARRAY      04d5df0c 4d5cf0c 000090 00  WA  0   0  4
[23] .ctors            PROGBITS        04d5df9c 4d5cf9c 000008 00  WA  0   0  4
[24] .dtors            PROGBITS        04d5dfa4 4d5cfa4 000008 00  WA  0   0  4
[25] .jcr              PROGBITS        04d5dfac 4d5cfac 000004 00  WA  0   0  4
[26] .data.rel.ro      PROGBITS        04d5dfc0 4d5cfc0 1b160c 00  WA  0   0 32
[27] .dynamic          DYNAMIC         04f0f5cc 4f0e5cc 000220 08  WA  6   0  4
[28] .got              PROGBITS        04f0f7ec 4f0e7ec 00a800 04  WA  0   0  4
[29] .data             PROGBITS        04f1a000 4f19000 0206b8 00  WA  0   0 32
[30] .bss              NOBITS          04f3a6c0 4f396b8 04c800 00  WA  0   0 32
[31] .comment          PROGBITS        00000000 4f396b8 00002a 01  MS  0   0  1
[32] .shstrtab         STRTAB          00000000 4f396e2 00013e 00      0   0  1
[33] .symtab           SYMTAB          00000000 4f39d98 4ff960 10     34 140163  4
[34] .strtab           STRTAB          00000000 54396f8 144992a 00      0   0  1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)

Должен ли я смотреть на .init или .init_array вместо этого? Не могли бы вы указать мне соответствующую документацию, которая объясняет изменение между версиями gcc или линкера?

3

Решение

Статические конструкторы могут быть вызваны любым из трех разделов .init, .ctors, или же .init_array (от старейшего до новейшего в этом порядке). .init содержит фрагмент кода, .ctors а также .init_array содержат указатели на код. Разница между .ctors а также .init_array имеет отношение к общему порядку выполнения конструкторов. Насколько я знаю, ничего из этого не задокументировано нигде, кроме комментариев к коду и сообщений в списке рассылки, но, вероятно, стоит проверить документы ELF ABI (g- и ps-оба).

Вы не могу вывести количество статических конструкторов в файле из размера любой из этих разделов. Допускается и обычно для компиляторов генерировать единственную специальную функцию, которая вызывает все конструкторы в файле и ссылается только на эту одну функцию в любом из разделов, которые она использует. Все, что вы можете знать наверняка (без изучения содержимого разделов, применения перемещений и указания указателей / инструкций вызова в .text сегмент и обратный инжиниринг, что бы ни называлось) это: в объектном файле, если хотя бы один из этих разделов имеет ненулевой размер, то в файле имеется хотя бы один конструктор файловой или глобальной области видимости; если все три раздела пусты, то их нет. (В исполняемом файле все три раздела всегда непусты, поскольку определяемые ими структуры данных нуждаются в заголовках и трейлерах, которые автоматически добавляются во время соединения.)

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

8

Другие решения

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

Затем вы можете измерить это более точно во время компиляции, при компиляции (с последней версией GCC, например, 4.7 или 4.8) вашего приложения. Вы могли бы расширить это с ПЛАВИТЬСЯ (это высокоуровневый предметно-ориентированный язык для расширения GCC), или с болезненными плагинами GCC, написанными на C ++, для измерения таких вещей.

И я не совсем уверен, что ваш вопрос имеет точный смысл. Если ваша заявка, например, связан с некоторой разделяемой библиотекой, которая использует уловки видимости, чтобы скрыть свои статические конструкторы, понимая, сколько статических конструкторов, которые вызывает библиотека, на самом деле не определено.

0

По вопросам рекламы [email protected]