исправление смещения .bss
This commit is contained in:
parent
9ba53693d5
commit
e54fb6a479
|
|
@ -125,10 +125,10 @@ def create_elf(text_bytes, data_bytes, pass1_data, labels, output_file):
|
|||
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text_bytes), align_up(len(text_bytes), PAGE_SIZE))
|
||||
|
||||
if bnd_size > 0:
|
||||
# Сегмент данных включает .data + .bss
|
||||
# p_filesz — только данные в файле, p_memsz — данные + BSS в памяти
|
||||
data_segment_filesz = len(data_bytes)
|
||||
data_segment_memsz = align_up(len(data_bytes) + bnd_size, PAGE_SIZE)
|
||||
# memsz должно покрывать от vaddr_data до конца .bss
|
||||
bss_end = vaddr_bnd + bnd_size
|
||||
data_segment_memsz = align_up(bss_end - vaddr_data, PAGE_SIZE)
|
||||
ph2 = phdr(1, 6, offset_data, vaddr_data, data_segment_filesz, data_segment_memsz)
|
||||
else:
|
||||
ph2 = phdr(1, 6, offset_data, vaddr_data, len(data_bytes), align_up(len(data_bytes), PAGE_SIZE))
|
||||
|
|
|
|||
23
kvs_pass1.py
23
kvs_pass1.py
|
|
@ -316,8 +316,8 @@ class Pass1:
|
|||
offset_data = align_up(offset_text + text_size, PAGE_SIZE)
|
||||
vaddr_text = text_vaddr_base
|
||||
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE)
|
||||
#vaddr_bnd = align_up(vaddr_data + data_size, PAGE_SIZE)
|
||||
vaddr_bnd = align_up(vaddr_data + max(data_size, 1), PAGE_SIZE)
|
||||
# .бнд всегда на следующей странице после .data
|
||||
vaddr_bnd = vaddr_data + PAGE_SIZE
|
||||
|
||||
comment_size = len("Сборщик КВС".encode('utf-8')) + 1
|
||||
offset_comment = align_up(offset_data + data_size, 1)
|
||||
|
|
@ -370,4 +370,21 @@ if __name__ == "__main__":
|
|||
|
||||
layout = pass1.calculate_layout()
|
||||
write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2])
|
||||
print(f"Проход 1: text_size={layout['text_size']}, data_size={layout['data_size']}, bnd_size={layout['bnd_size']}")
|
||||
|
||||
print(f"Проход 1:")
|
||||
print(f" .text: размер={layout['text_size']} байт, смещение_в_файле=0x{layout['offset_text']:x}, виртуальный_адрес=0x{layout['vaddr_text']:x}")
|
||||
print(f" .data: размер={layout['data_size']} байт, смещение_в_файле=0x{layout['offset_data']:x}, виртуальный_адрес=0x{layout['vaddr_data']:x}")
|
||||
print(f" .бнд: размер={layout['bnd_size']} байт, виртуальный_адрес=0x{layout['vaddr_bnd']:x}")
|
||||
print(f" entry_point: {layout['entry_point']}")
|
||||
print(f" метки:")
|
||||
for label, pos in pass1.labels.items():
|
||||
sec = pass1.label_sections.get(label, ".text")
|
||||
if sec == ".text":
|
||||
addr = layout['vaddr_text'] + pos
|
||||
elif sec == ".data":
|
||||
addr = layout['vaddr_data'] + pos
|
||||
elif sec == ".бнд":
|
||||
addr = layout['vaddr_bnd'] + pos
|
||||
else:
|
||||
addr = pos
|
||||
print(f" {label}: секция={sec}, смещение={pos}, адрес=0x{addr:x}")
|
||||
18
kvs_pass2.py
18
kvs_pass2.py
|
|
@ -65,7 +65,7 @@ def read_pass1(input_file):
|
|||
if parts[0] == "PARAM":
|
||||
key = parts[1]
|
||||
value = parts[2]
|
||||
if value.isdigit():
|
||||
if value.isdigit() or (value.startswith('-') and value[1:].isdigit()):
|
||||
value = int(value)
|
||||
data[key] = value
|
||||
elif parts[0] == "LABEL":
|
||||
|
|
@ -182,8 +182,8 @@ class Pass2:
|
|||
self.label_sections = label_sections
|
||||
self.symbols = symbols
|
||||
self.vaddr_text = pass1_data["vaddr_text"]
|
||||
text_size = pass1_data["text_size"]
|
||||
self.vaddr_data = align_up(self.vaddr_text + text_size, PAGE_SIZE)
|
||||
self.vaddr_data = pass1_data.get("vaddr_data", align_up(self.vaddr_text + pass1_data["text_size"], PAGE_SIZE))
|
||||
self.vaddr_bnd = pass1_data.get("vaddr_bnd", self.vaddr_data + PAGE_SIZE)
|
||||
self.position = {".text": 0, ".data": 0}
|
||||
self.current_section = ".text"
|
||||
self.csv_lines = []
|
||||
|
|
@ -211,7 +211,14 @@ class Pass2:
|
|||
op_str = operands[1]
|
||||
if op_str in self.labels:
|
||||
sec = self.label_sections[op_str]
|
||||
addr = self.labels[op_str] + (self.vaddr_text if sec == ".text" else self.vaddr_data)
|
||||
if sec == ".text":
|
||||
addr = self.labels[op_str] + self.vaddr_text
|
||||
elif sec == ".data":
|
||||
addr = self.labels[op_str] + self.vaddr_data
|
||||
elif sec == ".бнд":
|
||||
addr = self.labels[op_str] + self.vaddr_bnd
|
||||
else:
|
||||
addr = self.labels[op_str] + self.vaddr_text
|
||||
return hex(addr)
|
||||
elif op_str in self.symbols:
|
||||
return hex(self.symbols[op_str])
|
||||
|
|
@ -291,7 +298,8 @@ class Pass2:
|
|||
|
||||
current_pos = self.position[sec]
|
||||
code = encode_instruction(mnemonic, operands, self.labels, self.label_sections,
|
||||
self.symbols, self.vaddr_text, self.vaddr_data, current_pos)
|
||||
self.symbols, self.vaddr_text, self.vaddr_data, current_pos,
|
||||
self.vaddr_bnd)
|
||||
|
||||
target_addr = self.get_target_addr(mnemonic, operands)
|
||||
|
||||
|
|
|
|||
|
|
@ -55,10 +55,7 @@ def parse_operand(operand, labels, label_sections, symbols, vaddr_text, vaddr_da
|
|||
elif section == '.data':
|
||||
return labels[operand] + vaddr_data
|
||||
elif section == '.бнд':
|
||||
if vaddr_bnd is not None:
|
||||
return labels[operand] + vaddr_bnd
|
||||
else:
|
||||
return labels[operand] + vaddr_data
|
||||
return labels[operand] + vaddr_bnd
|
||||
else:
|
||||
return labels[operand] + vaddr_text
|
||||
if operand in symbols:
|
||||
|
|
@ -111,7 +108,7 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_
|
|||
elif section == '.data':
|
||||
base = vaddr_data
|
||||
elif section == '.бнд':
|
||||
base = vaddr_bnd if vaddr_bnd is not None else vaddr_data
|
||||
base = vaddr_bnd
|
||||
else:
|
||||
base = vaddr_text
|
||||
addr = labels[value] + base
|
||||
|
|
@ -140,7 +137,7 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_
|
|||
elif section == '.data':
|
||||
base = vaddr_data
|
||||
elif section == '.бнд':
|
||||
base = vaddr_bnd if vaddr_bnd is not None else vaddr_data
|
||||
base = vaddr_bnd
|
||||
else:
|
||||
base = vaddr_text
|
||||
addr = labels[content] + base
|
||||
|
|
|
|||
|
|
@ -88,4 +88,49 @@ _start:
|
|||
|
||||
## Как проверить
|
||||
|
||||
Если закомментировать Тест 3 (строки с `рсикс` и `неиниц_бнд`), код возврата станет `66` — баг исчезает, потому что `0x402000` не перезаписывается.
|
||||
Если закомментировать Тест 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` для меток `.бнд`.
|
||||
45
тесты/test_bss_only.квс
Normal file
45
тесты/test_bss_only.квс
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
.текст
|
||||
.глобал _start
|
||||
|
||||
_start:
|
||||
; =============================================
|
||||
; ТЕСТ 1: Абсолютная адресация в .бнд
|
||||
; =============================================
|
||||
переместить_имм раикс, 0x42
|
||||
сохранить [абс_перем], раикс
|
||||
|
||||
; =============================================
|
||||
; ТЕСТ 2: Косвенная адресация в .бнд
|
||||
; =============================================
|
||||
переместить_имм рбикс, косв_перем
|
||||
переместить_имм раикс, 0x99
|
||||
сохранить [рбикс], раикс
|
||||
|
||||
; =============================================
|
||||
; ТЕСТ 3: Ещё одна косвенная адресация в .бнд
|
||||
; =============================================
|
||||
переместить_имм рсикс, ещё_перем
|
||||
переместить_имм раикс, 0x77
|
||||
сохранить [рсикс], раикс
|
||||
|
||||
; =============================================
|
||||
; Читаем всё обратно
|
||||
; =============================================
|
||||
загрузить р8, [абс_перем]
|
||||
загрузить р9, [рбикс]
|
||||
загрузить р10, [рсикс]
|
||||
|
||||
; =============================================
|
||||
; ЗАВЕРШЕНИЕ: возвращаем из абс_перем
|
||||
; =============================================
|
||||
загрузить рдиай, [абс_перем]
|
||||
переместить_имм раикс, 60
|
||||
вызов_системы
|
||||
|
||||
.бнд
|
||||
абс_перем:
|
||||
.резб 1
|
||||
косв_перем:
|
||||
.резб 1
|
||||
ещё_перем:
|
||||
.резб 8
|
||||
Loading…
Reference in a new issue