aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/xixanta/src/assembler.rs67
-rwxr-xr-xscripts/test-e2e.sh5
-rw-r--r--tests/expected/variable_names.txt4
-rw-r--r--tests/variable_names.s25
4 files changed, 101 insertions, 0 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index 09f0c9d..01a1982 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -498,6 +498,13 @@ impl<'a> Assembler<'a> {
match self.evaluate_node(node.left.as_ref().unwrap()) {
Ok(value) => {
+ // Check that the given name makes sense if the
+ // address sanitizer is enable and the assigned
+ // value is known.
+ if self.asan_enabled && value.resolved {
+ self.asan_check_variable_name(node, &value);
+ }
+
if let Err(err) = self.context.set_variable(
&node.value,
&Object {
@@ -2626,6 +2633,66 @@ impl<'a> Assembler<'a> {
}
}
+ // Check that the variable name follows the coding convention as expected
+ // from the address sanitizer.
+ fn asan_check_variable_name(&mut self, node: &PNode, bundle: &Bundle) {
+ // If this is not an asan-friendly name, skip it, as it might be a
+ // constant or something else that might be catched later.
+ if !is_asan_friendly_name(&node.value.value) {
+ return;
+ }
+
+ // Let's create this object now to makes things easier for possible
+ // error messages.
+ let actual_name = node.value.value.split("::").last().unwrap_or("");
+
+ if actual_name.starts_with("zp_") {
+ if bundle.size > 1 {
+ let value = bundle.value() as usize;
+ let range = MemoryRange {
+ name: node.value.value.to_owned(),
+ range: (value..(value + self.asan_next_reserve as usize)),
+ };
+ self.warnings.push(Error {
+ line: node.value.line,
+ message: format!("you are assigning the zero-page variable {range} to something outside of zero page"),
+ source: self.source_for(node),
+ global: false,
+ });
+ }
+ } else if bundle.size != 2 {
+ let value = bundle.value() as usize;
+ let range = MemoryRange {
+ name: node.value.value.to_owned(),
+ range: (value..(value + self.asan_next_reserve as usize)),
+ };
+ self.warnings.push(Error {
+ line: node.value.line,
+ message: format!(
+ "you are assigning the variable {range} to something in zero page"
+ ),
+ source: self.source_for(node),
+ global: false,
+ });
+ } else if actual_name.starts_with("wr_") {
+ let value = bundle.value() as usize;
+ let range = MemoryRange {
+ name: node.value.value.to_owned(),
+ range: (value..(value + self.asan_next_reserve as usize)),
+ };
+ if !(0x6000..0x8000).contains(&value) {
+ self.warnings.push(Error {
+ line: node.value.line,
+ message: format!(
+ "you are assigning the variable {range} to something outside of Working RAM"
+ ),
+ source: self.source_for(node),
+ global: false,
+ });
+ }
+ }
+ }
+
fn to_relative_address(&self, node: &PNode, bundle: &mut Bundle) -> Result<(), Error> {
if !bundle.resolved {
return Ok(());
diff --git a/scripts/test-e2e.sh b/scripts/test-e2e.sh
index ab7312b..1c94cfd 100755
--- a/scripts/test-e2e.sh
+++ b/scripts/test-e2e.sh
@@ -61,6 +61,11 @@ echo "test: custom => bare_accesses.nes"
diff tests/out/bare_accesses.txt tests/expected/bare_accesses.txt
exit_code=$((exit_code + $?))
+echo "test: custom => variable_names.nes"
+./target/debug/nasm -c empty --asan tests/variable_names.s 2>tests/out/variable_names.txt
+diff tests/out/variable_names.txt tests/expected/variable_names.txt
+exit_code=$((exit_code + $?))
+
##
# code.nes
diff --git a/tests/expected/variable_names.txt b/tests/expected/variable_names.txt
new file mode 100644
index 0000000..416ca69
--- /dev/null
+++ b/tests/expected/variable_names.txt
@@ -0,0 +1,4 @@
+warning: you are assigning the zero-page variable 'zp_bad' ($0300) to something outside of zero page (variable_names.s: line 11)
+warning: you are assigning the variable 'm_bad' ($02) to something in zero page (variable_names.s: line 13)
+warning: you are assigning the variable 'wr_bad' ($01) to something in zero page (variable_names.s: line 14)
+warning: you are assigning the variable 'wr_out' ($0400) to something outside of Working RAM (variable_names.s: line 16)
diff --git a/tests/variable_names.s b/tests/variable_names.s
new file mode 100644
index 0000000..0859473
--- /dev/null
+++ b/tests/variable_names.s
@@ -0,0 +1,25 @@
+.segment "HEADER"
+ .byte 'N', 'E', 'S', $1A
+ .byte $02
+ .byte $01
+ .byte $12 ; let's fake working RAM
+ .byte $00
+
+.segment "CODE"
+
+zp_good = $00
+zp_bad = $0300
+m_good = $0200
+m_bad = $02
+wr_bad = $01
+wr_good = $6001
+wr_out = $0400
+
+;; Just so we don't get "unused" warnings
+lda zp_bad
+lda zp_good
+lda m_bad
+lda m_good
+lda wr_bad
+lda wr_good
+lda wr_out