Как объявить массив C, который занимает все свободное место в разделе памяти?

Предположим, у меня есть область памяти 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.


person Andrew Cottrell    schedule 21.09.2010    source источник


Ответы (5)


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

Короткий ответ: «нет».

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

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

person Dummy00001    schedule 21.09.2010
comment
Green Hills не использует набор инструментов GNU. У него есть совместимость с GNU, но он сам по себе зверь. См. комментарий @PatrickSchlüter - person John Burger; 12.09.2016

Обычно вы делаете это с чем-то вроде:

extern char section_bss[];

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

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

person nategoose    schedule 21.09.2010

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

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

person Patrick Schlüter    schedule 22.09.2010

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

person supercat    schedule 21.09.2010

Что случилось с

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.

person Quuxplusone    schedule 06.09.2012