OpenWiki

Palm Multi Segment

Palm Notes | Recent Changes | Title Index | User Preferences | Random Page | Help
Difference from revision 3 to the current revision.
major diff minor diff author diff hide diff

Статья 
объясняет 
идеологию 
мультисегментных приложений для PalmOS с использованием GCC.
  
В 
информатике 
существует 
малоизвестный термин ABI - Application Binary Interface. Этим термином называют набор особенностей компьютерной архитектуры, которые нужно учитывать при создании приложения. ABI может накладываться процессором: направление роста стека, размер элемента данных в стеке, порядок байт в слове итд. Также ABI может накладываться операционной системой. Тогда в ABI входит способ вызова системного API, специфика использования адресного пространства и прочие нюансы. Изменения, которые вносятся в GCC для компиляции под PalmOS, нужны именно для соответствия PalmOS ABI.
  
Что такое 
приложение с 
точки зрения 
PalmOS? Приложение 
- это база 
ресурсов. 
Четыре 
ресурса из 
этой базы 
используются для исполнения программы.
Это ресурс 'code' #1,
в котором
собственно и
хранится
исполняемый
код, который
запускается
с нулевого
байта
ресурса.
Также из
ресурса 'code' #0
берется
размеры
области
глобальных
данных. Из
ресурса 'pref' #0
берется
размер стека.
И ресурс 'data' #0 
используется
для 
инициализации
глобальных
данных. Все!
До всего
остального
содержимого
базы
приложения PalmOS
дела нет.
Подробности
можно
почитать
здесь:
http://www.linuxmafia.com/pub/palmos/development/prc-format.html
  
Такой способ
позволяет
запускать
программы
практически
"на месте",
выделяя
только
память под
стек и
глобальные
переменные.
  
Какие 
ограничения 
накладываются на простое односегментное приложение? 
  
  1  * Размер
ресурса 'code' #0
ограничен 64К.
Это
ограничение
было у PalmOS
включая
версию 4 и у
Хотсинка до
версии 5 
включительно.
Условное
ограничение
сегмента GCC в 32К
лечится
заменой
скрипта для
линкера на text_64k.
  2  *
Ограничение
смещения у
команды
вызова
процедуры в
32К. То есть,
если сегмент
больше 32К, то
функция из
начала не
может
вызвать
функцию в
конце
сегмента. Это
можно обойти
путем
перемещения
вызываемых
функций
"поближе" к
вызываемым
или
созданием 
прокси-функций 
функций-заглушек
в середине
сегмента.
  
    *
Ограничение
размера
глобальных
данных
программы.
Общий объем
глобальных
данных (в
сумме 
инициализированных
и 
неинициализированных)
должен 
укладываться
в 64К. Замечу,
что
константные 
инициализированные
данные
помещаются в
сегмент кода.
  
Что
усложнится
при попытке
добавить
новый
сегмент?
  
  
Самая
большая
проблема - 
межсегментный
вызов
процедуры. В
случае
одного
сегмента
расстояние
между
процедурами
постоянно и
код вызова не
меняется
после
компиляции. В
случае 
межсегментного
вызова
ресурсы
могут 
располагаться
в 
произвольных
участках
памяти и
смещение
нужно 
корректировать.
  
Замечу, что в 
односегментном
приложении
также
происходит
коррекция
области
данных. В
нижележащем
примере
значение
переменной pfn
будет 
скорректировано.
Это возможно,
поскольку
сегмент
данных
находится в 
динамической
памяти.
Копировать
же все
сегменты в 
динамическую
память для
коррекции
неразумно и 
расточительно.
<code>
void foo(void){
}
  
void *pfn = foo;
</code>
  
Все (оба ;-) ) 
производители 
компиляторов
для PalmOS
предлагают
свои
поддержки 
мультисегментности.
  
Gcc предлагает
следующий
способ:
  * Всем
функциям 
приписывается
атрибут с
именем
сегмента.
Функции
помещаются в 
соответствующие
сегменты 
единственного
получаемого
ELF-файла.
  * В области
глобальных
переменных
хранятся
адреса всех
сегментов
  * При вызове
функции из
другого
семента
происходит
сложение
смещения
функции от
начала
сегмента к
адресу
сегмента из
глобальной
памяти
  
В чем
ограничения
такого
метода:
  * 
Использование
глобальных
данных. Это
обозначает,
что при
вызове
программы
без
глобальных
переменных,
вызов
функций из
других
сегментов
попросту
невозможен.
При попытке
вызвать
произойдет
обращение к 
несуществующей
области
глобалных
данных и Fatal Alert
неизбежен.
  * Этот способ
никак не
расширяет
область
глобальных
данных.
  * Проблемы с
доступом к
константным
данным.
Константные
данные могут
оказаться в
другом
сегменте и
тебовать
наличия
глобальных
данных.
  * Неявные
функции и
методы
класса. C++
богат на
неявную
генерацию
неявного
кода. Следует 
контролировать
куда будет
помещен код
темплейтов и
не
инлайновых
инлайнов.
Подробное
описание 
мультисегментной
архитектуры
GCC здесь:
http://prc-tools.sourceforge.net/doc/prc-tools_3.html
  
  
Существует 
альтернативный
способ
создания 
мультисегментных
приложений с
помощью
утилиты multilink.
Смотри
описание
здесь: http://www.djw.org/product/palm/multilink/
  
Multilink
использует
другую идею:
  * Исходные
файлы 
компилируются
как обычно. Не
нужно
указывать
сегменты в
исходном
коде
  * Утилита
получает на
вход
объектные
файлы и 
необязательный
список
разбиения
функций по
сегментам.
  * Утилита
разбивает
все функции
по сегментам
по списку и
добивает
оставшиеся
до
указанного
размера
сегментов.
  * Если
функция foo из
сегмента segA
вызывает  bar из
сегмента srgB, то
в segA
добавляется
заглушка для
bar, вызывающая bar.
  * Для
вычисления
адреса bar 
используются
данные,
которые
хранятся в feature memory.
Тем самым
наличие
глобальных
данных 
необязательно.
  * Полученные
сегменты
добавляются
в программу.
  
У этого
решения есть
один большой
минус -
невозможен
доступ к
константным
данным из
другого
сегмента.
  
  
  

Palm Notes | Recent Changes | Title Index | User Preferences | Random Page | Help
Edit this page | View other revisions
Print this page | View XML
Find page by browsing, searching or an index
Edited December 2, 2003 (hide diff)