Просмотр точного диапазона памяти, который компоновщик «использует» для исполняемого двоичного файла - PullRequest
0 голосов
/ 06 февраля 2020

Я делаю немного OSdev, и я пытался реализовать управление памятью в моем ядре. Я начал с менеджера физической памяти (это 32-битная ОС). Идея состоит в том, чтобы сохранить таблицу битов, в которой мы выделяем бит для блока физической памяти 4K. Если бит равен «1», блок используется, а если «0», это не так. Я думал, что эта таблица должна идти после ядра. Итак, вот мой код ядра (минимальный):

#include<stdint.h> 

#define PMMAP 0x1000 //This contains information from int 15h/E820
#define BLOCK_SIZE 4096
#define SECTOR_SIZE 512
#define SECTORS_PER_BLOCK 8
#define BLOCK_SIZE_B 12
#define SECTOR_SIZE_B 9
#define SECTORS_PER_BLOCK_B 3

void  pmmngr_init(uint32_t kernelsize,uint32_t mapentrycount);
uint32_t* _physical_memory_table;

void kmain(uint32_t size,uint32_t mmapentrycount)   //This size is passed on by the bootloader, where it has a filesystem driver-ish code that determines this. The size unit is 512 bytes
{
    pmmngr_init(size,mmapentrycount);
    return;
}
struct mmap_entry {
    uint32_t  startLo;
    uint32_t  startHi;
    uint32_t  sizeLo;
    uint32_t  sizeHi;
    uint32_t  type;
    uint32_t  acpi_3_0;
  };
void  pmmngr_init(uint32_t kernelsize,uint32_t mapentrycount)
{ 
    struct mmap_entry* map_ptr= (struct mmap_entry*)PMMAP;

    _physical_memory_table = (uint32_t*)(KERNEL_P + kernelsize*SECTOR_SIZE); 

    for (uint32_t i=0;i<0x8000;i++)  //Why 0x8000? This is the size of the table (* 32 of course)
            _physical_memory_table[i] = 0xffffffff;

}

Изначально я делаю все 0xffffffff. Затем я читаю карту памяти (из E820) и выделяю и освобождаю (позже).

Я компилирую с:

i686-elf-gcc kernel.c -c -g -o kernel.o --ffreestanding
i686-elf-ld kernel.o -Ttext 0x100000 -o kernel.elf
objcopy -O binary kernel.elf kernel.bin

Обратите внимание, что ядро ​​предназначено для загрузки в область памяти 1M. Все это было введением в эту проблему. Вот основная проблема ..

Здесь моя _physical_memory_table загружается / создается после ядра, и место его создания зависит от размера файла kernel.bin, полученного из загрузчик.

Предположим, размер файла kernel.bin составляет ~ 1 КБ. Таблица будет размещена в памяти размером 1 МБ + 1 КБ (0x100400). Вот основная проблема ... указатель переменной _physical_memory_table на самом деле не «размещен» в диапазоне 0x100000 - 0x100400 компоновщиком. Он принадлежит разделу .bss и, в моем случае, находится вне этого диапазона! Указатель присутствует в том месте, где создается таблица, он перекрывается и, таким образом, это ошибка.

Итак, как бы я решил эту проблему? Мне нужно раскрыть «диапазон контроля» ядра, т. Е. Диапазон ядра и всех его частей в памяти, и поместить эту таблицу после .

Так что же делать Я делаю? (Я предполагаю что-то с помощью скрипта компоновщика)

1 Ответ

1 голос
/ 06 февраля 2020

Вы захотите использовать собственный скрипт компоновщика для ядра. В скрипте были бы нормальные разделы для .text, .rodata, .data, .bss и некоторых других. Обычай состоит в том, чтобы определять символы для каждого раздела для начала и конца для текущего адреса в процессе связывания, например, _text_start = . и _text_end = . вокруг элементов в разделе .text.

В вашем C код, который вы можете затем объявить переменными:

extern void *_text_start[], *_text_end[];

Затем эти адреса будут заполнены компоновщиком и сообщат вам, где начинается и заканчивается каждый раздел вашего ядра. Часто у вас также есть символ _end после всех разделов. Обычно это идентично _bss_end, с последним разделом .bss.

Ваше ядро ​​поместит _physical_memory_table после _end, чтобы избежать любых совпадений с самим собой.

Хотя большинство людей включают фиксированную исходную _physical_memory_table в их разделы .data или .bss, которые просто отображают 4 ГБ памяти 1: 1. Когда MMU запущен и работает, и вы переключились на kernel_start (), правильная, мелкозернистая таблица памяти может быть легко настроена с помощью кода C.

В моем ядре я также включаю 64 КБ неиспользуемой памяти в Раздел .bss, который используется для управления памятью. Таким образом, с самого начала доступно 64 КБ памяти для выделения. Код, который анализирует карту памяти, может затем выделить структуры данных из этого пула, прежде чем он добавит свободные области памяти к распределителю.

...