Как объявить массив C, который занимает все свободное место в разделе памяти? - PullRequest
3 голосов
/ 22 сентября 2010

Предположим, у меня есть область памяти 128 КБ.В моих директивах компоновщика я разделил этот регион на три раздела:

  • .section_text
  • .section_data
  • .section_bss

Размеркаждой секции неизвестна предварительная компиляция, но я ограничил .section_bss использовать все оставшееся пространство в области памяти после выделения .section_text и .section_data.

Есть ли способ объявить массив C, которыйзанимает все доступное пространство в .region_bss?Предположим, что это единственное, что использует .region_bss, поэтому он может безопасно использовать весь регион.Для примера, но, очевидно, неправильно:

char entire_bss[sizeof(.region_bss)];

Вот мои предварительные ответы на некоторые ожидаемые ответы.Во-первых, я знаю, что sizeof () не работает так.Я просто использую это, чтобы донести идею.Во-вторых, предположим, что это должно быть сделано с массивом, а не с указателями (решение с помощью указателей возможно и довольно просто).В-третьих, я знаю, что могу получить начальный и конечный адреса .region_bss, но я не знаю ни одного способа использовать их для определения размера моего массива.По крайней мере, не так, как это работает в C.

Возможно, нет никакого способа сделать это, но я надеюсь, что какой-то гений это понял.Дополнительный кредит, если вы можете заставить его работать с набором инструментов Green Hills.

Ответы [ 5 ]

2 голосов
/ 22 сентября 2010

Нет, ты не можешь. Также легко понять почему. На этапе компиляции нет понятия .bss и .data, это чистые соглашения о компоновщике. Компилятору известны некоторые абстрактные понятия (постоянные данные, статические данные, код), но их сопоставление с разделом компоновщика является лишь условным соглашением и зависит от параметров компоновщика, ОС и процессора или даже модели памяти. При построении независимого от позиции кода часто константы, например, помещаются в сегмент кода. На встроенных платформах вам иногда приходится сталкиваться с этими вещами и даже вынуждены адаптировать свой стиль кодирования из-за этого (у нас когда-то была модель, основанная на процессорах 80186, построенных с помощью компилятора MS-C 5.1, где мы не могли использовать * Раздел 1001 * (глобальные, инициализированные переменные и статика), поскольку набор инструментов помещает их в ПЗУ.

Однажды мы решили похожую проблему, исправив сгенерированный двоичный файл в конце всего процесса сборки. Мы извлекли использованную память другого раздела из файла карты, сгенерированного компоновщиком (это вариант поиска), и вычли его из объема памяти данной модели (у нас было модели 256K, 512K и 896K) и установили один глобальных констант с правильным значением. Поэтому было важно, чтобы все ссылки на этот размер работали через эту глобальную переменную. Этот пул памяти был использован нашей реализацией malloc / free.

2 голосов
/ 22 сентября 2010

Можно ли как-нибудь объявить массив C, который использует все доступное пространство в .region_bss?

Краткий ответ "нет".

Если GreenHills использует набор инструментов GNU с binutils и позволяет настраивать скрипт компоновщика , то вы можете добавить в пространство имен приложения переменную , используя PROVIDE, чтобы отметить конец блока 128К. (См. Пример, как получить доступ к таким переменным здесь ). Таким образом, у вас не будет массива C фиксированного размера, но программа сможет найти конец массива, то есть размер массива, который обычно достаточен для программ на C.

Если вы хотите выполнить это с использованием чистого C99, то вам может не повезти, так как это крайне ненадежно , поскольку это не предусмотрено стандартом.

2 голосов
/ 22 сентября 2010

Обычно вы делаете это с помощью чего-то вроде:

extern char section_bss[];

С добавлением некоторых дополнительных вещей, чтобы компилятор, ассемблер и компоновщик знали, что section_bss является псевдонимом для .section_bss(или похожее имя).

Чтобы получить размер, вы, вероятно, захотите сделать то же самое для символа в конце bss и найти разницу.

0 голосов
/ 06 сентября 2012

Что не так с

extern char __ghsbegin_region_bss[];
extern char __ghssize_region_bss[];
#define entire_bss __ghsbegin_region_bss
#define sizeof_entire_bss ((size_t)__ghssize_region_bss)

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

Обратите внимание, что __ghssize_region_bss не является константой времени компиляции - она ​​не разрешается до времени компоновки - поэтому у 100% нет способа получить ее внутри [...] типа массива во время компиляции.

См. Главу «Начало, конец и размер символов сечений» в руководстве по Green Hills.

0 голосов
/ 22 сентября 2010

То, что вы хотите сделать, будет зависеть от платформы. Лучше всего объявить массив как extern char the_array [], end_of_array []; в вашем C-файле, а затем, возможно, в исходном файле на ассемблере, объявите несколько разделов данных для the_array и end_of_array. Затем расположите спецификацию компоновщика так, чтобы the_array был в конце материала, который расположен снизу вверх, и end_of_array будет в начале материала, который расположен сверху вниз, и между ними больше ничего не будет. Это возможно - я сделал это на некоторых платформах - но важно внимательно прочитать документацию компоновщика, чтобы убедиться, что компоновщик не будет перестраивать вещи, когда вы этого не ожидаете.

...