summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcadmic <cadmic24@gmail.com>2026-07-30 22:28:40 -0700
committerGitHub <noreply@github.com>2026-07-31 07:28:40 +0200
commit32b88f90a86a024dae0af0dc28a2c5e023fd193a (patch)
treec6abd43184bb805c5da7dd12c4af00781e761175
parent269d03016cd0e3d7a0b8925e02b97a319c1d0e8d (diff)
Fix fix_bss.py tiebreaking algorithm (#2779)
-rwxr-xr-xtools/fix_bss.py24
1 files changed, 18 insertions, 6 deletions
diff --git a/tools/fix_bss.py b/tools/fix_bss.py
index 4c9d22937..d6200a357 100755
--- a/tools/fix_bss.py
+++ b/tools/fix_bss.py
@@ -32,7 +32,6 @@ from ido_block_numbers import (
import elftools.elf.elffile
import mapfile_parser.mapfile
-
# Set on program start since we replace sys.stdout in worker processes
stdout_isatty = sys.stdout.isatty()
@@ -337,6 +336,7 @@ class Pragma:
@dataclass
class BssVariable:
block_number: int
+ is_top_level: bool
name: str
size: int
align: int
@@ -395,9 +395,12 @@ def find_bss_variables(
if block_number in init_block_numbers:
continue # not BSS
- name = symbol_table[block_number].name
if op.opcode_name == "fsym":
- name = f"{last_function_name}::{name}"
+ name = f"{last_function_name}::{symbol_table[block_number].name}"
+ is_top_level = False
+ else:
+ name = symbol_table[block_number].name
+ is_top_level = True
size = op.args[0]
align = 1 << op.lexlev
@@ -408,7 +411,9 @@ def find_bss_variables(
referenced_in_data = block_number in referenced_in_data_block_numbers
bss_variables.append(
- BssVariable(block_number, name, size, align, referenced_in_data)
+ BssVariable(
+ block_number, is_top_level, name, size, align, referenced_in_data
+ )
)
elif op.opcode_name == "init":
if op.dtype == 10: # Ndt, "non-local label"
@@ -439,10 +444,16 @@ def predict_bss_ordering(variables: list[BssVariable]) -> list[BssSymbol]:
# For variables referenced in .data or .rodata, keep the original order.
referenced_in_data = [var for var in variables if var.referenced_in_data]
- # For the others, sort by block number mod 256. For ties, sort by block number.
+ # For the others, sort by block number mod 256. Ties are broken with the following priority:
+ # 1. top-level global and static variables, in original (block number) order
+ # 2. in-function static variables, in reverse order
not_referenced_in_data = [var for var in variables if not var.referenced_in_data]
not_referenced_in_data.sort(
- key=lambda var: (var.block_number % 256, var.block_number)
+ key=lambda var: (
+ var.block_number % 256,
+ not var.is_top_level,
+ var.block_number if var.is_top_level else -var.block_number,
+ )
)
sorted_variables = referenced_in_data + not_referenced_in_data
@@ -588,6 +599,7 @@ def solve_bss_ordering(
new_bss_variables.append(
BssVariable(
new_block_number,
+ var.is_top_level,
var.name,
var.size,
var.align,