ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
13 июля
495073
fk0, легенда (08.03.2014 04:33, просмотров: 830)
Зачем нужны GOT таблицы? Ведь в сегменте данных всё лежит уже в известном линкеру порядке, неизвестно только смещение. Почему бы в спец. регистре процессора хранить не адрес GOT-таблицы, а самого сегмента данных и относительно его начала и не адресовать бы? Код короче и быстрей. Я про переменные. Сегмент данных случае мешанины из библиотек распределён хаотичным образом. Без гота пришлось бы перед вызовом функции из конкретной библиотеки заново устанавливать базовый регистр на её кусок сегмента данных. Но если хочется обратного. Сегмент данных, положим, линкером распределён на этапе компиляции и вообще не волнует. Хочется присутстия кода в сегменте кода по мере надобности. Потому, что адресное пространство маленькое и весь код разом не влезает. Т.е. PLT и GOT тут нужны. В готе не нужно ничего кроме функций. Идея в том, что если функция в памяти -- GOT содержит её адрес и она прямо практически вызывается. А если её нет в памяти, то гот содержит адрес загрузчика, который загрузит функцию (выкинув парочку других по мере надобности) и вызовет её, поместив в GOT её адрес. Нет так не заработает. Если выкинуть из памяти функцию из которой вызвали данную (или более верхнюю в стеке), то куда потом возвращаться? Стало быть вызов через PLT где-то должен записывать функции, которые вызываются (в том же стеке) и при попытке выкинуть что-то из памяти нужно просматривать стек на предмет того, что функции сейчас заняты (вызвана и не вернулась: присутствует в стеке выше SP). Callbacks тоже через PLT должны работать. Вроде всё сходится, должно работать? Не совсем понятно только, как заставить GCC нагенерить код с адресацией данных как есть, по абсолютным адресам, и с адресацией кода через PLT и GOT. И ещё чтоб в PLT враппер свой засунуть, которые в стеке односвязаный список вызванных функций поддерживать будет. :-/ Для чего это. Интересная получается штука, что можно программы большего размера исполнять из ОЗУ меньшего объёма. Для ембеддед программ харатерно, что sizeof(.text) >> sizeof(.data+.bss). Поэтому данные можно распределить на этапе компиляции. А текст компилировать с -fpic и подгружать в свободную память по мере надобности, совершенно прозрачно для программ, для которых как бы вся программа разом в памяти. Почему? Потому, что внешний SDRAM требует кешей и дорогих МК. Внешний SRAM дорог, занимает много площади, тоже жрёт электричество. МК с большими объёмами Flash дороже чем без Flash вообще. При том в таких МК уже есть какой-то объём RAM, которого чуть-чуть не хватает. А ряд ембеддед приложений всё равно требует носителя данных в роли которого выступает NOR-flash -- зачем платить дважды (за флеш в МК маленького размера, когда есть внешний существенно большего). Конечно есть и другой подход. Все программы не нужны одновременно. Можно разделить ПО на ряд независимых приложений и загружать часть из них последовательно, по мере надобности (вот где нужна ОС). Но совсем уж глубоко разделить не получится. Останется монолитная достаточно большая программа. И понятно, что большая часть её функций всё равно 99% времени не нужна.
[ZX]