04-06-2023
В информатике, таблица символов является структурой данных используемой транслятором (компилятором или интерпретатором), где каждый идентификатор переменной из исходного кода ассоциируется с информацией, связанной с его объявлением или появлением в коде, такой как тип, область видимости и в некоторых случаях место в памяти (смещение).
Общеиспользуемой реализацией является хеш-таблица. Компилятор может как использовать единую таблицу для символов, так и разделять символы на несколько иерархических таблиц по разным областям видимости. Бывают также реализации в виде деревьев, линейных и самоорганизовываемых списков.
Объектный модуль (англ. object file) содержит таблицу символов для внешне видимых (публичных) идентификаторов. На протяжении компонования (линковки) разных объектных модулей, компоновщик использует таблицы символов для разрешения межмодульных упоминаний.
Таблица символов может существовать лишь на протяжении трансляции, но иногда она вкладывается в вывод этого процесса для дальнейшего использования, например, во время интерактивной отладки, или как источник для форматирования диагностического отчета во время или после исполнения программы.
Во время реверс-инжиниринга, многие утилиты с помощью таблицы проверяют, каким адресам принадлежат глобальные переменные и известные функции. Если таблица символов была убрана из объектных модулей до линковки (например, с помощью strip из GNU binutils), утилитам будет сложнее определить адреса важных мест программы и проанализировать ее.
При доступе к переменным и динамическом распределении памяти, компилятор должен осуществить множество работ, отсюда - расширенной модели стека при динамическом распределении необходима таблица символов.[прояснить]
Хорошим примером использования таблицы символов могут послужить модульные ядра ОС семейства Unix: таблица символов может использоваться подгружаемыми модулями ядра (например, драйверами) для доступа к неким символам. Однако это не является обязательным если модуль не обращается к ядру, не использует внутренние функции, переменные, и т.д.[1] Возможно обойтись без таблицы символов и обращаться к памяти внутри ядра напрямую, но в этом случае будет потеряна переносимость модулей, т.к. при разных конфигурациях ядра, одинаковый код будет размещен в разных местах.
Снизу приведена таблица символов небольшой программы. Для ее создания использовалась утилита тип символа, третья - его название.
Адрес | Тип | Имя |
---|---|---|
00000020 | a | T_BIT |
00000040 | a | F_BIT |
00000080 | a | I_BIT |
20000004 | t | irqvec |
20000008 | t | fiqvec |
2000000c | t | InitReset |
20000018 | T | _main |
20000024 | t | End |
20000030 | T | AT91F_US3_CfgPIO_useB |
2000005c | t | AT91F_PIO_CfgPeriph |
200000b0 | T | main |
20000120 | T | AT91F_DBGU_Printk |
20000190 | t | AT91F_US_TxReady |
200001c0 | t | AT91F_US_PutChar |
200001f8 | T | AT91F_SpuriousHandler |
20000214 | T | AT91F_DataAbort |
20000230 | T | AT91F_FetchAbort |
2000024c | T | AT91F_Undef |
20000268 | T | AT91F_UndefHandler |
20000284 | T | AT91F_LowLevelInit |
200002e0 | t | AT91F_DBGU_CfgPIO |
2000030c | t | AT91F_PIO_CfgPeriph |
20000360 | t | AT91F_US_Configure |
200003dc | t | AT91F_US_SetBaudrate |
2000041c | t | AT91F_US_Baudrate |
200004ec | t | AT91F_US_SetTimeguard |
2000051c | t | AT91F_PDC_Open |
2000059c | t | AT91F_PDC_DisableRx |
200005c8 | t | AT91F_PDC_DisableTx |
200005f4 | t | AT91F_PDC_SetNextTx |
20000638 | t | AT91F_PDC_SetNextRx |
2000067c | t | AT91F_PDC_SetTx |
200006c0 | t | AT91F_PDC_SetRx |
20000704 | t | AT91F_PDC_EnableRx |
20000730 | t | AT91F_PDC_EnableTx |
2000075c | t | AT91F_US_EnableTx |
20000788 | T | __aeabi_uidiv |
20000788 | T | __udivsi3 |
20000884 | T | __aeabi_uidivmod |
2000089c | T | __aeabi_idiv0 |
2000089c | T | __aeabi_ldiv0 |
2000089c | T | __div0 |
200009a0 | D | _data |
200009a0 | A | _etext |
200009a0 | D | holaamigosh |
200009a4 | A | __bss_end__ |
200009a4 | A | __bss_start |
200009a4 | A | __bss_start__ |
200009a4 | A | _edata |
200009a4 | A | _end |
Таблица символов.