From 6aabd55c96a276e8e40ef6198ef23fac2143f345 Mon Sep 17 00:00:00 2001 From: aissata Date: Fri, 25 Mar 2022 09:44:07 +0100 Subject: [PATCH 1/9] - feature: + supported in ORIGIN - added test --- Cargo.toml | 2 +- src/main.rs | 139 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 105 insertions(+), 36 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7fe16bb..c630d51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ env_logger = { version = "0.9", default-features = false } log = "0.4" object = { version = "0.26", default-features = false, features = ["read_core", "elf", "std"] } getrandom = "0.2" - +regex = "1.5.5" [dev-dependencies] assert_cmd = "2.0" rstest = "0.11" diff --git a/src/main.rs b/src/main.rs index 02e189f..464be28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -269,6 +269,15 @@ macro_rules! eat { } }; } +macro_rules! tryc { + ($expr:expr) => { + if let Ok(x) = $expr { + x + } else { + continue; + } + }; +} fn get_includes_from_linker_script(linker_script: &str) -> Vec<&str> { let mut includes = vec![]; @@ -284,16 +293,6 @@ fn get_includes_from_linker_script(linker_script: &str) -> Vec<&str> { /// Looks for "RAM : ORIGIN = $origin, LENGTH = $length" // FIXME this is a dumb line-by-line parser fn find_ram_in_linker_script(linker_script: &str) -> Option { - macro_rules! tryc { - ($expr:expr) => { - if let Ok(x) = $expr { - x - } else { - continue; - } - }; - } - for (index, mut line) in linker_script.lines().enumerate() { line = line.trim(); line = eat!(line, "RAM"); @@ -306,38 +305,21 @@ fn find_ram_in_linker_script(linker_script: &str) -> Option { line = eat!(line, ":"); line = eat!(line, "ORIGIN"); line = eat!(line, "="); + println!("Printing line: {}", line); + let boundary_pos = tryc!(line.find(|c| c == ',').ok_or(())); + println!("Printing line2: {}", &line[..boundary_pos]); + + let origin = arithmetic_op(&line[..boundary_pos]); - let boundary_pos = tryc!(line.find(|c| c == ',' || c == ' ').ok_or(())); - const HEX: &str = "0x"; - let origin = if line.starts_with(HEX) { - tryc!(u64::from_str_radix(&line[HEX.len()..boundary_pos], 16)) - } else { - tryc!(line[..boundary_pos].parse()) - }; line = line[boundary_pos..].trim(); + println!("Printing line3: {}", line); line = eat!(line, ","); line = eat!(line, "LENGTH"); line = eat!(line, "="); - let segments: Vec<&str> = line.split('+').map(|s| s.trim().trim_end()).collect(); - let mut total_length = 0; - for segment in segments { - let boundary_pos = segment - .find(|c| c == 'K' || c == 'M') - .unwrap_or(segment.len()); - let length: u64 = tryc!(segment[..boundary_pos].parse()); - let raw = &segment[boundary_pos..]; - let mut chars = raw.chars(); - let unit = chars.next(); - if unit == Some('K') { - total_length += length * 1024; - } else if unit == Some('M') { - total_length += length * 1024 * 1024; - } else if unit == None { - total_length += length; - } - } + let total_length = arithmetic_op(line); + return Some(MemoryEntry { line: index, origin, @@ -348,6 +330,41 @@ fn find_ram_in_linker_script(linker_script: &str) -> Option { None } +fn arithmetic_op(line: &str) -> u64 { + let segments: Vec<&str> = line.split('+').map(|s| s.trim().trim_end()).collect(); + // if some numbers are hex we convert here + + let mut total_length = 0; + for segment in segments { + println!("current segment {}", segment); + let boundary_pos = segment + .find(|c| c == 'K' || c == 'M') + .unwrap_or(segment.len()); + println!("boundary pos {}", boundary_pos); + const HEX: &str = "0x"; + let length: u64 = if segment.starts_with(HEX) { + tryc!(u64::from_str_radix(&segment[HEX.len()..boundary_pos], 16)) + } else { + tryc!(segment[..boundary_pos].parse()) + }; + println!("hex length {}", length); + + let raw = &segment[boundary_pos..]; + println!("rest of the segment {}", &segment[boundary_pos..]); + let mut chars = raw.chars(); + let unit = chars.next(); + if unit == Some('K') { + total_length += length * 1024; + } else if unit == Some('M') { + total_length += length * 1024 * 1024; + } else if unit == None { + total_length += length; + } + } + println!("total length : {}", total_length); + total_length +} + #[cfg(test)] mod tests { use super::*; @@ -430,6 +447,58 @@ INCLUDE device.x ); } + #[test] + fn parse_plus_origin_k() { + const LINKER_SCRIPT: &str = "MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 2M + RAM : ORIGIN = 0x20020000 + 100K, LENGTH = 368K +} + +INCLUDE device.x +"; + + assert_eq!( + find_ram_in_linker_script(LINKER_SCRIPT), + Some(MemoryEntry { + line: 3, + origin: 0x20020000 + (100 * 1024), + length: 368 * 1024, + }) + ); + + assert_eq!( + get_includes_from_linker_script(LINKER_SCRIPT), + vec!["device.x"] + ); + } + + #[test] + fn parse_plus_origin_m() { + const LINKER_SCRIPT: &str = "MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 2M + RAM : ORIGIN = 0x20020000 + 100M, LENGTH = 368K +} + +INCLUDE device.x +"; + + assert_eq!( + find_ram_in_linker_script(LINKER_SCRIPT), + Some(MemoryEntry { + line: 3, + origin: 0x20020000 + (100 * 1024 * 1024), + length: 368 * 1024, + }) + ); + + assert_eq!( + get_includes_from_linker_script(LINKER_SCRIPT), + vec!["device.x"] + ); + } + // test attributes https://sourceware.org/binutils/docs/ld/MEMORY.html #[test] fn parse_attributes() { From ac543962a4214647cc7f51ea2257cda9ab954014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=C3=AFssata=20Maiga?= <40670675+Dajamante@users.noreply.github.com> Date: Mon, 4 Apr 2022 15:33:32 +0200 Subject: [PATCH 2/9] Update Cargo.toml Co-authored-by: Johann Hemmann --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c630d51..635d1de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ env_logger = { version = "0.9", default-features = false } log = "0.4" object = { version = "0.26", default-features = false, features = ["read_core", "elf", "std"] } getrandom = "0.2" -regex = "1.5.5" +regex = "1.5" [dev-dependencies] assert_cmd = "2.0" rstest = "0.11" From bb3140679a33ae5f5ca4d5663d174a1188263f75 Mon Sep 17 00:00:00 2001 From: aissata Date: Mon, 4 Apr 2022 15:49:03 +0200 Subject: [PATCH 3/9] addressed Johann's comments --- src/main.rs | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 464be28..a7e1f33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -269,6 +269,8 @@ macro_rules! eat { } }; } + +/// This macro search `token` in a line and returns it, or , else `continue` loop iteration. macro_rules! tryc { ($expr:expr) => { if let Ok(x) = $expr { @@ -305,20 +307,17 @@ fn find_ram_in_linker_script(linker_script: &str) -> Option { line = eat!(line, ":"); line = eat!(line, "ORIGIN"); line = eat!(line, "="); - println!("Printing line: {}", line); let boundary_pos = tryc!(line.find(|c| c == ',').ok_or(())); - println!("Printing line2: {}", &line[..boundary_pos]); - let origin = arithmetic_op(&line[..boundary_pos]); + let origin = perform_addition(&line[..boundary_pos]); line = line[boundary_pos..].trim(); - println!("Printing line3: {}", line); line = eat!(line, ","); line = eat!(line, "LENGTH"); line = eat!(line, "="); - let total_length = arithmetic_op(line); + let total_length = perform_addition(line); return Some(MemoryEntry { line: index, @@ -330,27 +329,24 @@ fn find_ram_in_linker_script(linker_script: &str) -> Option { None } -fn arithmetic_op(line: &str) -> u64 { +/// Perform addition when ORIGN or LENGTH variables contain an addition +fn perform_addition(line: &str) -> u64 { let segments: Vec<&str> = line.split('+').map(|s| s.trim().trim_end()).collect(); - // if some numbers are hex we convert here let mut total_length = 0; for segment in segments { - println!("current segment {}", segment); let boundary_pos = segment .find(|c| c == 'K' || c == 'M') .unwrap_or(segment.len()); - println!("boundary pos {}", boundary_pos); const HEX: &str = "0x"; + // Special case parsing for hex numbers. let length: u64 = if segment.starts_with(HEX) { tryc!(u64::from_str_radix(&segment[HEX.len()..boundary_pos], 16)) } else { tryc!(segment[..boundary_pos].parse()) - }; - println!("hex length {}", length); + }; // if some numbers are hex we convert here let raw = &segment[boundary_pos..]; - println!("rest of the segment {}", &segment[boundary_pos..]); let mut chars = raw.chars(); let unit = chars.next(); if unit == Some('K') { @@ -361,7 +357,6 @@ fn arithmetic_op(line: &str) -> u64 { total_length += length; } } - println!("total length : {}", total_length); total_length } @@ -473,6 +468,32 @@ INCLUDE device.x ); } + #[test] + fn parse_plus_origin_no_units() { + const LINKER_SCRIPT: &str = "MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 2M + RAM : ORIGIN = 0x20020000 + 1000, LENGTH = 368K +} + +INCLUDE device.x +"; + + assert_eq!( + find_ram_in_linker_script(LINKER_SCRIPT), + Some(MemoryEntry { + line: 3, + origin: 0x20020000 + 1000, + length: 368 * 1024, + }) + ); + + assert_eq!( + get_includes_from_linker_script(LINKER_SCRIPT), + vec!["device.x"] + ); + } + #[test] fn parse_plus_origin_m() { const LINKER_SCRIPT: &str = "MEMORY From 8c900c2a14bff0fdef74b911648a9cc1fdcb215a Mon Sep 17 00:00:00 2001 From: aissata Date: Mon, 4 Apr 2022 16:01:36 +0200 Subject: [PATCH 4/9] Typo! --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index a7e1f33..fff05f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -344,7 +344,7 @@ fn perform_addition(line: &str) -> u64 { tryc!(u64::from_str_radix(&segment[HEX.len()..boundary_pos], 16)) } else { tryc!(segment[..boundary_pos].parse()) - }; // if some numbers are hex we convert here + }; let raw = &segment[boundary_pos..]; let mut chars = raw.chars(); From 9d6409fd65e0f78a2f2d61e07fae8740996ea6cf Mon Sep 17 00:00:00 2001 From: aissata Date: Mon, 4 Apr 2022 16:31:37 +0200 Subject: [PATCH 5/9] addressed Johann's comments 2 --- src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index fff05f6..b0dbbe2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -270,7 +270,7 @@ macro_rules! eat { }; } -/// This macro search `token` in a line and returns it, or , else `continue` loop iteration. +/// This macro takes any expression which evaluates to a Result, returns the Ok value, or continues in case of an Err. macro_rules! tryc { ($expr:expr) => { if let Ok(x) = $expr { @@ -329,7 +329,8 @@ fn find_ram_in_linker_script(linker_script: &str) -> Option { None } -/// Perform addition when ORIGN or LENGTH variables contain an addition +/// Perform addition when ORIGN or LENGTH variables contain an addition. +/// If there is no addition to be performed, it will return the `u64` value. fn perform_addition(line: &str) -> u64 { let segments: Vec<&str> = line.split('+').map(|s| s.trim().trim_end()).collect(); From 2a36f8bd369b802452a9dd1c55ac973c3ccadcb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=C3=AFssata=20Maiga?= <40670675+Dajamante@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:45:27 +0200 Subject: [PATCH 6/9] Update src/main.rs Co-authored-by: Johann Hemmann --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index b0dbbe2..55d1be5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -270,7 +270,7 @@ macro_rules! eat { }; } -/// This macro takes any expression which evaluates to a Result, returns the Ok value, or continues in case of an Err. +/// This macro takes any expression which evaluates to a `Result`, returns the `Ok` value, or continues in case of an `Err`. macro_rules! tryc { ($expr:expr) => { if let Ok(x) = $expr { From 011d5cc4dd89694c201d1218b1d5e9f02439b036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=C3=AFssata=20Maiga?= <40670675+Dajamante@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:46:06 +0200 Subject: [PATCH 7/9] Update Cargo.toml Co-authored-by: Johann Hemmann --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 635d1de..b9ad0f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,8 @@ env_logger = { version = "0.9", default-features = false } log = "0.4" object = { version = "0.26", default-features = false, features = ["read_core", "elf", "std"] } getrandom = "0.2" -regex = "1.5" +regex = "1.5" + [dev-dependencies] assert_cmd = "2.0" rstest = "0.11" From 5a9d731e5859fc8e0fbe2aa656aa931bfc72e1d1 Mon Sep 17 00:00:00 2001 From: aissata Date: Mon, 4 Apr 2022 17:38:09 +0200 Subject: [PATCH 8/9] added tests for perform_addition --- src/main.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main.rs b/src/main.rs index b0dbbe2..7bf87d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -417,6 +417,22 @@ INCLUDE device.x ); } + #[test] + fn test_perform_addition_hex_and_number() { + const ADDITION: &str = "0x20000000 + 1000"; + let expected: u64 = 0x20000000 + 1000; + + assert_eq!(perform_addition(ADDITION), expected); + } + + #[test] + fn test_perform_addition_returns_number() { + const NO_ADDITION: &str = "0x20000000"; + let expected: u64 = 536870912; //0x20000000 base 10 + + assert_eq!(perform_addition(NO_ADDITION), expected); + } + #[test] fn parse_plus() { const LINKER_SCRIPT: &str = "MEMORY From 5cddd90635c9dab49db4f5bdbf4ce2ff2a49d14d Mon Sep 17 00:00:00 2001 From: aissata Date: Mon, 4 Apr 2022 17:46:08 +0200 Subject: [PATCH 9/9] Good bye Regex --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b9ad0f0..7fe16bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ env_logger = { version = "0.9", default-features = false } log = "0.4" object = { version = "0.26", default-features = false, features = ["read_core", "elf", "std"] } getrandom = "0.2" -regex = "1.5" [dev-dependencies] assert_cmd = "2.0"