Как объединить все данные после кода в одном чистом бинарном файле?

Здравствуйте! У меня возникла проблема с размещением данных строго после кода в готовом бинарном файле без формата. 

Вот что я сделал:

1. Компилировал файл с помощью команды:
   ```bash
   x86_64-elf-gcc -m32 -ffreestanding -c kernel.c -o kernel.o
   ```
2. Линковал объектный файл с помощью команды:
   ```bash
   ld.lld -T linker.ld -o kernel --oformat binary kernel.o
   ```

Теперь, в самом коде на C, я объявляю массивы вне функций следующим образом:
```cpp
__attribute__((section(".data_kdata")))
char SCANCODES_QEMU[58] = {
    '?', '?', '1', '2', '3', '4', '5', '6', '7', '8', 
    '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 
    't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '?', 
    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 
    '\'', '`', '?', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 
    'm', ',', '.', '/', '?', '?', '?', ' '
};
```

Я использую атрибут для любых глобальных данных в секции. Однако, несмотря на это, данные в бинарном файле располагаются не так, как я ожидал: сначала идут строки и массивы, затем код, и снова массивы. Как мне правильно расположить данные в бинарном файле?
  • 17 января 2025 г. 8:54
Ответы на вопрос 2
Для того чтобы данные располагались в бинарном файле строго после кода, вам необходимо правильно настроить файл скрипта компоновщика `linker.ld`. Ваша проблема, скорее всего, заключается в том, что текущая конфигурация скрипта компоновщика не соответствует вашим ожиданиям по расположению секций.

Вот шаги, которые вам нужно выполнить, чтобы убедиться, что глобальные массивы располагаются непосредственно после кода:

### 1. Настройка скрипта компоновщика

Ваш скрипт компоновщика `linker.ld` должен точно указывать порядок размещения секций. Вот упрощенный пример того, как может выглядеть файл `linker.ld`:

```ld
OUTPUT_FORMAT("binary")

SECTIONS
{
    . = 0x1000; /* Начальный адрес загрузки, вы можете изменить его на нужный вам */

    .text : {
        *(.text)       /* Все секции .text (код) */
    }
    
    .data_kdata : {
        *(.data_kdata) /* Все секции .data_kdata (данные) */
    }
    
    .bss : {
        *(.bss)        /* Все секции .bss (неинициализированные данные) */
    }
}
```

### 2. Использование атрибутов секций в коде

Вы уже правильно добавили атрибут секции `__attribute__((section(".data_kdata")))` к вашему массиву. Убедитесь, что вы используете правильные секции для всех глобальных данных, включая неинициализированные данные.

### 3. Компиляция и линковка

После того, как вы обновите файл компоновщика, выполните те же шаги компиляции и линковки:

```bash
x86_64-elf-gcc -m32 -ffreestanding -c kernel.c -o kernel.o
ld.lld -T linker.ld -o kernel --oformat binary kernel.o
```

### 4. Проверка результата

Теперь после компиляции и линковки проверьте бинарный файл, чтобы убедиться, что данные располагаются прямо после кода. Вы можете использовать инструменты, такие как `xxd` или `hexdump`, чтобы просмотреть содержимое бинарного файла:

```bash
xxd kernel
```

Если вы всё сделали правильно, ваши глобальные данные должны находиться сразу после секции кода `.text`, и вы больше не увидите разрыва секций, которые могут привести к смешиванию данных.

Если у вас по-прежнему возникают проблемы, убедитесь, что не осталось лишних секций и что вы не используете дополнительные атрибуты, которые могут влиять на размещение ваших данных и кода.
Нужно явно указать секцию .rodata после секции .text 
и attribute section после этого не понадобится:

SECTIONS
{
. = 0x100200;

.text :
{
*(.text)
}

.rodata : <- тут явно указываем секцию
{
*(.rodata)
}

.data :
{
*(.data)
}

.bss :
{
*(.bss)
}

. = ALIGN(4);
}
Похожие вопросы