исправление смещения .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))
|
ph1 = phdr(1, 5, offset_text, vaddr_text, len(text_bytes), align_up(len(text_bytes), PAGE_SIZE))
|
||||||
|
|
||||||
if bnd_size > 0:
|
if bnd_size > 0:
|
||||||
# Сегмент данных включает .data + .bss
|
|
||||||
# p_filesz — только данные в файле, p_memsz — данные + BSS в памяти
|
|
||||||
data_segment_filesz = len(data_bytes)
|
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)
|
ph2 = phdr(1, 6, offset_data, vaddr_data, data_segment_filesz, data_segment_memsz)
|
||||||
else:
|
else:
|
||||||
ph2 = phdr(1, 6, offset_data, vaddr_data, len(data_bytes), align_up(len(data_bytes), PAGE_SIZE))
|
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)
|
offset_data = align_up(offset_text + text_size, PAGE_SIZE)
|
||||||
vaddr_text = text_vaddr_base
|
vaddr_text = text_vaddr_base
|
||||||
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE)
|
vaddr_data = align_up(vaddr_text + text_size, PAGE_SIZE)
|
||||||
#vaddr_bnd = align_up(vaddr_data + data_size, PAGE_SIZE)
|
# .бнд всегда на следующей странице после .data
|
||||||
vaddr_bnd = align_up(vaddr_data + max(data_size, 1), PAGE_SIZE)
|
vaddr_bnd = vaddr_data + PAGE_SIZE
|
||||||
|
|
||||||
comment_size = len("Сборщик КВС".encode('utf-8')) + 1
|
comment_size = len("Сборщик КВС".encode('utf-8')) + 1
|
||||||
offset_comment = align_up(offset_data + data_size, 1)
|
offset_comment = align_up(offset_data + data_size, 1)
|
||||||
|
|
@ -370,4 +370,21 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
layout = pass1.calculate_layout()
|
layout = pass1.calculate_layout()
|
||||||
write_pass1(layout, pass1.labels, pass1.label_sections, pass1.symbols, sys.argv[2])
|
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":
|
if parts[0] == "PARAM":
|
||||||
key = parts[1]
|
key = parts[1]
|
||||||
value = parts[2]
|
value = parts[2]
|
||||||
if value.isdigit():
|
if value.isdigit() or (value.startswith('-') and value[1:].isdigit()):
|
||||||
value = int(value)
|
value = int(value)
|
||||||
data[key] = value
|
data[key] = value
|
||||||
elif parts[0] == "LABEL":
|
elif parts[0] == "LABEL":
|
||||||
|
|
@ -182,8 +182,8 @@ class Pass2:
|
||||||
self.label_sections = label_sections
|
self.label_sections = label_sections
|
||||||
self.symbols = symbols
|
self.symbols = symbols
|
||||||
self.vaddr_text = pass1_data["vaddr_text"]
|
self.vaddr_text = pass1_data["vaddr_text"]
|
||||||
text_size = pass1_data["text_size"]
|
self.vaddr_data = pass1_data.get("vaddr_data", align_up(self.vaddr_text + pass1_data["text_size"], PAGE_SIZE))
|
||||||
self.vaddr_data = align_up(self.vaddr_text + text_size, PAGE_SIZE)
|
self.vaddr_bnd = pass1_data.get("vaddr_bnd", self.vaddr_data + PAGE_SIZE)
|
||||||
self.position = {".text": 0, ".data": 0}
|
self.position = {".text": 0, ".data": 0}
|
||||||
self.current_section = ".text"
|
self.current_section = ".text"
|
||||||
self.csv_lines = []
|
self.csv_lines = []
|
||||||
|
|
@ -211,7 +211,14 @@ class Pass2:
|
||||||
op_str = operands[1]
|
op_str = operands[1]
|
||||||
if op_str in self.labels:
|
if op_str in self.labels:
|
||||||
sec = self.label_sections[op_str]
|
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)
|
return hex(addr)
|
||||||
elif op_str in self.symbols:
|
elif op_str in self.symbols:
|
||||||
return hex(self.symbols[op_str])
|
return hex(self.symbols[op_str])
|
||||||
|
|
@ -291,7 +298,8 @@ class Pass2:
|
||||||
|
|
||||||
current_pos = self.position[sec]
|
current_pos = self.position[sec]
|
||||||
code = encode_instruction(mnemonic, operands, self.labels, self.label_sections,
|
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)
|
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':
|
elif section == '.data':
|
||||||
return labels[operand] + vaddr_data
|
return labels[operand] + vaddr_data
|
||||||
elif section == '.бнд':
|
elif section == '.бнд':
|
||||||
if vaddr_bnd is not None:
|
return labels[operand] + vaddr_bnd
|
||||||
return labels[operand] + vaddr_bnd
|
|
||||||
else:
|
|
||||||
return labels[operand] + vaddr_data
|
|
||||||
else:
|
else:
|
||||||
return labels[operand] + vaddr_text
|
return labels[operand] + vaddr_text
|
||||||
if operand in symbols:
|
if operand in symbols:
|
||||||
|
|
@ -111,7 +108,7 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_
|
||||||
elif section == '.data':
|
elif section == '.data':
|
||||||
base = vaddr_data
|
base = vaddr_data
|
||||||
elif section == '.бнд':
|
elif section == '.бнд':
|
||||||
base = vaddr_bnd if vaddr_bnd is not None else vaddr_data
|
base = vaddr_bnd
|
||||||
else:
|
else:
|
||||||
base = vaddr_text
|
base = vaddr_text
|
||||||
addr = labels[value] + base
|
addr = labels[value] + base
|
||||||
|
|
@ -140,7 +137,7 @@ def parse_memory_operand(operand_str, labels, label_sections, vaddr_text, vaddr_
|
||||||
elif section == '.data':
|
elif section == '.data':
|
||||||
base = vaddr_data
|
base = vaddr_data
|
||||||
elif section == '.бнд':
|
elif section == '.бнд':
|
||||||
base = vaddr_bnd if vaddr_bnd is not None else vaddr_data
|
base = vaddr_bnd
|
||||||
else:
|
else:
|
||||||
base = vaddr_text
|
base = vaddr_text
|
||||||
addr = labels[content] + base
|
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