kvs/тесты/bss_bug.txt

136 lines
6.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Исходник
```asm
.текст
.глобал _start
_start:
; ТЕСТ 1: Абсолютная адресация в .data
переместить_имм раикс, 0x42
сохранить [абс_данные], раикс ; запись 0x42 по адресу абс_данные (0x402000)
; ТЕСТ 2: Косвенная адресация в .data
переместить_имм рбикс, косв_данные ; рбикс = адрес косв_данные (0x402001)
переместить_имм раикс, 0x99
сохранить [рбикс], раикс ; запись 0x99 по адресу 0x402001
; ТЕСТ 3: Косвенная адресация в .бнд
переместить_имм рсикс, неиниц_бнд ; рсикс = адрес неиниц_бнд
переместить_имм раикс, 0x77
сохранить [рсикс], раикс ; запись 0x77 по адресу неиниц_бнд
; Читаем всё обратно
загрузить р8, [абс_данные] ; чтение из 0x402000
загрузить р9, [рбикс] ; чтение из 0x402001
загрузить р10, [рсикс] ; чтение из неиниц_бнд
; ЗАВЕРШЕНИЕ: возвращаем значение из абс_данные
загрузить рдиай, [абс_данные] ; рдиай = значение из 0x402000
переместить_имм раикс, 60 ; номер системного вызова exit
вызов_системы
.данные
абс_данные:
.байт 0
косв_данные:
.байт 0
.бнд
неиниц_бнд:
.резб 8
```
## Размещение секций в памяти
```
0x401000 ─ .text (код)
0x402000 ─ .data
├── абс_данные (смещение 0): байт 0
└── косв_данные (смещение 1): байт 0
0x403000 ─ .бнд
└── неиниц_бнд (смещение 0): 8 байт, ноль
```
## Что подразумевается
1. **Тест 1** пишет `0x42` в `абс_данные` по адресу `0x402000`.
2. **Тест 2** пишет `0x99` в `косв_данные` по адресу `0x402001`.
3. **Тест 3** пишет `0x77` в `неиниц_бнд` по адресу **`0x403000`**.
После этого:
- `[0x402000]` содержит `0x42`
- `[0x402001]` содержит `0x99`
- `[0x403000]` содержит `0x77`
Финал читает `[абс_данные]` = `[0x402000]` = `0x42` в `рдиай` и завершается.
**Ожидаемый код возврата:** `66` (это `0x42`).
## Что происходит на самом деле
**Фактический код возврата:** `119` (это `0x77`).
## Причина
Инструкция `переместить_имм рсикс, неиниц_бнд` загружает в `рсикс` **неправильный адрес**. Вместо `0x403000` (адрес `.бнд`) регистр получает `0x402002` (адрес внутри `.data`).
Это происходит потому, что при вычислении адреса метки `неиниц_бнд` компилятор ошибочно использует базовый адрес секции `.data` (`0x402000`) вместо базового адреса секции `.бнд` (`0x403000`).
Смещение метки `неиниц_бнд` внутри `.бнд` равно `0`. Правильный расчёт должен быть: `0x403000 + 0 = 0x403000`. Но компилятор считает: `0x402000 + 0 = 0x402000`.
## Цепочка последствий
1. `рсикс` получает `0x402000` вместо `0x403000`.
2. `сохранить [рсикс], раикс` пишет `0x77` по адресу `0x402000` — **это ячейка `абс_данные`**.
3. Значение `0x42`, записанное в Тесте 1, **затирается** значением `0x77`.
4. Финал читает `[абс_данные]` и получает `0x77` вместо `0x42`.
5. Код возврата становится `119` вместо `66`.
## Как проверить
Если закомментировать Тест 3 (строки с `рсикс` и `неиниц_бнд`), код возврата станет `66` — баг исчезает, потому что `0x402000` не перезаписывается.
`vaddr_data` считается в **двух** местах:
### 1. `kvs_pass1.py` — метод `calculate_layout`
```python
vaddr_text = text_vaddr_base # 0x401000
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) # 0x402000
vaddr_bnd = align_up(vaddr_data + data_size, PAGE_SIZE) # 0x402000 или 0x403000
```
Эти значения записываются в pass1-файл как `PARAM:vaddr_text:...`, `PARAM:vaddr_data:...`, `PARAM:vaddr_bnd:...`.
### 2. `kvs_pass2.py` — конструктор `Pass2.__init__`
```python
self.vaddr_text = pass1_data["vaddr_text"] # читает из pass1
self.vaddr_data = align_up(self.vaddr_text + text_size, PAGE_SIZE) # вычисляет заново
```
**Pass2 не читает `vaddr_data` из pass1, а вычисляет сам.** А `vaddr_bnd` не читает и не вычисляет вообще.
### 3. `kvs_builder.py` — функция `create_elf`
```python
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE) # вычисляет заново
vaddr_bnd = pass1_data.get("vaddr_bnd", ...) # читает из pass1
```
**Builder читает `vaddr_bnd` из pass1**, но энкодер (pass2) его не получает.
---
## Корень бага
| Модуль | `vaddr_data` | `vaddr_bnd` |
|--------|:-----------:|:----------:|
| pass1 | вычисляет ✅ | вычисляет ✅ |
| pass2 | вычисляет ✅ | **не читает** ❌ |
| builder | вычисляет ✅ | читает из pass1 ✅ |
| encoder (mutsize) | получает от pass2 ✅ | **не получает** ❌ |
Pass2 не передаёт `vaddr_bnd` в энкодер, поэтому `parse_operand` получает `vaddr_bnd=None` и подставляет `vaddr_data` для меток `.бнд`.