Integrate all the progress into master #6
|
@ -1,196 +1,8 @@
|
|||
pub mod types;
|
||||
|
||||
use tool_helper::{Error, Input};
|
||||
use std::io::BufRead;
|
||||
use types::{Content, Section};
|
||||
use tool_helper::Error;
|
||||
use types::MemoryMap;
|
||||
|
||||
pub fn scan(input: Input) -> Result<Vec<Section>, Error> {
|
||||
let sections = process(input.lines().map(|l| l.unwrap()).into_iter())?;
|
||||
|
||||
Ok(sections)
|
||||
}
|
||||
|
||||
fn process<F: std::iter::Iterator<Item=String>>(mut line_iter:F) -> Result<Vec<Section>, Error> {
|
||||
let mut sections = Vec::new();
|
||||
while let Some(mut line) = line_iter.next() {
|
||||
loop {
|
||||
if line.starts_with(".") {
|
||||
let (new_line, new_section) = process_section(line, &mut line_iter)?;
|
||||
|
||||
sections.push(new_section);
|
||||
line = new_line;
|
||||
}
|
||||
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sections.sort_by(|left, right| {
|
||||
left.adr.cmp(&right.adr)
|
||||
});
|
||||
Ok(sections)
|
||||
}
|
||||
|
||||
fn process_section<F: std::iter::Iterator<Item=String>>(line: String, line_iter:&mut F) -> Result<(String, Section), Error> {
|
||||
let mut next_line_closure = || {
|
||||
line_iter.next().ok_or(Error::from_str("Unexpected end of file"))
|
||||
};
|
||||
let (mut section, line) = read_section(line, &mut next_line_closure)?;
|
||||
|
||||
Ok((process_subsection(&mut section, line, &mut next_line_closure)?, section))
|
||||
}
|
||||
|
||||
fn process_subsection<F:FnMut()-> Result<String, Error>>(section: &mut Section, line: Option<String>, next_line: &mut F) -> Result<String, Error> {
|
||||
fn push_sub_section(section: &mut Section, sub_section: Option<Section>) {
|
||||
if let Some(sub_section) = sub_section {
|
||||
section.content.push(Content::Section(sub_section));
|
||||
}
|
||||
}
|
||||
fn add_element<T>(sub_section: Option<Section>, section: &mut Section, value: T, callback: fn(&mut Section, T)) -> Option<Section> {
|
||||
if let Some(mut sub_section) = sub_section {
|
||||
callback(&mut sub_section, value);
|
||||
Some(sub_section)
|
||||
}
|
||||
|
||||
else {
|
||||
callback(section, value);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
let mut line = {
|
||||
if let Some(line) = line {
|
||||
line
|
||||
}
|
||||
|
||||
else {
|
||||
next_line()?
|
||||
}
|
||||
};
|
||||
|
||||
let mut next_line_closure = || -> Result<String, Error> {
|
||||
if let Ok(line) = next_line() {
|
||||
return Ok(line);
|
||||
}
|
||||
|
||||
else {
|
||||
// EOF
|
||||
return Ok(String::from(""));
|
||||
}
|
||||
};
|
||||
|
||||
let mut sub_section = None;
|
||||
|
||||
loop {
|
||||
if line.starts_with(" .") {
|
||||
push_sub_section(section, sub_section);
|
||||
let (section, new_line) = read_section(line, &mut next_line_closure)?;
|
||||
|
||||
sub_section = Some(section);
|
||||
|
||||
if let Some(new_line) = new_line {
|
||||
line = new_line;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else if line.starts_with(" *fill*") {
|
||||
let fill = read_fill(line)?;
|
||||
sub_section = add_element(sub_section, section, fill, |section, fill| {
|
||||
section.content.push(Content::Fill(fill));
|
||||
});
|
||||
}
|
||||
|
||||
else if line.starts_with(" 0x") {
|
||||
if let Some(symbol) = parse_symbol(read_symbol(line)?) {
|
||||
sub_section = add_element(sub_section, section, symbol, |section, symbol| {
|
||||
section.content.push(Content::Symbol(symbol));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else if line.is_empty() {
|
||||
push_sub_section(section, sub_section);
|
||||
return Ok(line);
|
||||
}
|
||||
|
||||
line = next_line_closure()?;
|
||||
}
|
||||
}
|
||||
|
||||
fn read_section<F:FnMut()-> Result<String, Error>>(mut line: String, next_line: &mut F) -> Result<(Section, Option<String>), Error> {
|
||||
let mut split_line = line.split_whitespace();
|
||||
let name = split_line.next().ok_or(Error::from_str("Couldn't locate section name"))?.to_string();
|
||||
let need_new_line = name.chars().count() > 16;
|
||||
|
||||
if need_new_line {
|
||||
line = next_line()?;
|
||||
split_line = line.split_whitespace();
|
||||
}
|
||||
|
||||
let adr = read_as::<u64>(split_line.next());
|
||||
if adr.is_none() {
|
||||
return Ok((Section::new(name, None, None, None), {
|
||||
if need_new_line {
|
||||
Some(line)
|
||||
}
|
||||
|
||||
else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
let size = read_as::<usize>(split_line.next());
|
||||
let file = {
|
||||
if let Some(file) = split_line.next() {
|
||||
Some(file.to_string())
|
||||
}
|
||||
|
||||
else {
|
||||
None
|
||||
}
|
||||
};
|
||||
Ok((Section::new(name, adr, size, file), None))
|
||||
}
|
||||
|
||||
fn read_fill(line: String) -> Result<types::Fill, Error> {
|
||||
let mut split_line = line.split_whitespace().skip(1);
|
||||
let adr = read_as::<u64>(split_line.next()).ok_or_else(|| {return Error::from_str("*fill* statement requires an address")})?;
|
||||
let size = read_as::<usize>(split_line.next()).ok_or_else(|| {return Error::from_str("*fill* statement requires a size")})?;
|
||||
|
||||
Ok(types::Fill::new(adr, size))
|
||||
}
|
||||
|
||||
fn read_symbol(line: String) -> Result<types::Symbol, Error> {
|
||||
let mut split_line = line.split_whitespace();
|
||||
let adr = read_as::<u64>(split_line.next()).ok_or_else(|| {return Error::from_str("Symbol statement requires an address")})?;
|
||||
let mut name = split_line.next().ok_or_else(|| {return Error::from_str("Symbol statement requires a symbol name")})?.to_string();
|
||||
|
||||
for fragment in split_line {
|
||||
name += fragment;
|
||||
}
|
||||
|
||||
Ok(types::Symbol::new(name, adr))
|
||||
}
|
||||
|
||||
fn parse_symbol(mut symbol: types::Symbol) -> Option<types::Symbol> {
|
||||
if symbol.name.starts_with(".") {
|
||||
return None;
|
||||
}
|
||||
|
||||
symbol.name = symbol.name.split('=').next().unwrap().to_owned();
|
||||
Some(symbol)
|
||||
}
|
||||
|
||||
fn read_as<F: num_traits::Num>(str: Option<&str>) -> Option<F> {
|
||||
if let Some(str) = str {
|
||||
F::from_str_radix(str.trim_start_matches("0x"), 16).ok()
|
||||
}
|
||||
|
||||
else {
|
||||
None
|
||||
}
|
||||
pub fn scan<F: FnMut() -> Option<String>>(_next_line: F) -> Result<MemoryMap, Error> {
|
||||
Err(Error::not_implemented("scan"))
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use clap::Parser;
|
||||
use readmap::types::{Content::*, Section};
|
||||
use tool_helper::{Error, exit_with_error};
|
||||
use std::{fs::File, io::{BufRead, BufReader, BufWriter, Write}, path::PathBuf, process::{Child, Command, Stdio}};
|
||||
use std::{io::{BufRead, BufReader}, path::PathBuf, process::{Child, Command, Stdio}};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(about = "Opens and scans a MAP file to print extended information", long_about = None)]
|
||||
|
@ -15,13 +14,8 @@ struct CommandLine {
|
|||
fn run_objdump(use_wsl: bool, input: PathBuf) -> Result<Child, Error> {
|
||||
let command_list = ["wsl", "objdump", "-x"];
|
||||
let start_idx = {
|
||||
if use_wsl {
|
||||
0
|
||||
}
|
||||
|
||||
else {
|
||||
1
|
||||
}
|
||||
if use_wsl {0}
|
||||
else {1}
|
||||
};
|
||||
let mut process = Command::new(command_list[start_idx]);
|
||||
|
||||
|
@ -30,65 +24,23 @@ fn run_objdump(use_wsl: bool, input: PathBuf) -> Result<Child, Error> {
|
|||
}
|
||||
process.arg(input.to_str().ok_or_else(||{Error::from_str("Failed converting input string")})?);
|
||||
|
||||
println!("Miau: {:?}", process);
|
||||
Ok(process.stdout(Stdio::piped()).spawn()?)
|
||||
}
|
||||
|
||||
fn run_main(cmd: CommandLine) -> Result<(), Error> {
|
||||
let mut child = run_objdump(cmd.use_wsl, cmd.input)?;
|
||||
if let Some(stdout) = &mut child.stdout {
|
||||
for line in BufReader::new(stdout).lines() {
|
||||
if let Ok(line) = line {
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
let mut line_iter = BufReader::new(stdout).lines().map(|l| l.unwrap()).into_iter();
|
||||
|
||||
readmap::scan(|| {
|
||||
line_iter.next()
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn _run_main(cmd: CommandLine) -> Result<(), Error> {
|
||||
fn value_to_hex<T: std::fmt::UpperHex>(value: T) -> String {
|
||||
return format!("0x{:X}", value);
|
||||
else {
|
||||
Err(Error::from_str("Failed opening \"stdout\" for objdump"))
|
||||
}
|
||||
|
||||
fn option_to_hex<T: std::fmt::UpperHex>(value: Option<T>) -> String {
|
||||
if let Some(value) = value {
|
||||
return value_to_hex(value);
|
||||
}
|
||||
|
||||
else {
|
||||
return String::from("<None>");
|
||||
}
|
||||
}
|
||||
|
||||
let sections = readmap::scan(tool_helper::open_input(Some(cmd.input))?)?;
|
||||
let mut file = tool_helper::open_output_file(&PathBuf::from("./planschi.d"))?;
|
||||
|
||||
for section in sections {
|
||||
fn print_content(tab_level: usize, file: &mut BufWriter<File>, section: Section) -> Result<(), Error> {
|
||||
for content in section.content {
|
||||
match content {
|
||||
Fill(fill) => {
|
||||
writeln!(file, "{:>tab_level$}*fill* @{}, {}", ' ', value_to_hex(fill.adr), value_to_hex(fill.size), tab_level=tab_level*4)?;
|
||||
},
|
||||
Section(section) => {
|
||||
writeln!(file, "{:>tab_level$} {} @{}, {}", ' ', section.name, option_to_hex(section.adr), option_to_hex(section.size), tab_level=tab_level*4)?;
|
||||
print_content(tab_level + 1, file, section)?;
|
||||
},
|
||||
Symbol(symbol) => {
|
||||
writeln!(file, "{:>tab_level$}{} @{}", ' ', symbol.name, value_to_hex(symbol.adr), tab_level=tab_level*4)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
writeln!(file, "{}: @{}, {}", section.name, option_to_hex(section.adr), option_to_hex(section.size))?;
|
||||
print_content(1, &mut file, section)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
use std::default::Default;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MemoryMap {
|
||||
pub global: Vec<Symbol>,
|
||||
pub sections: Vec<Section>
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Section {
|
||||
pub name: String,
|
||||
pub adr: Option<u64>,
|
||||
pub size: Option<usize>,
|
||||
pub file: Option<String>,
|
||||
pub content: Vec<Content>
|
||||
pub adr: u64,
|
||||
pub size: usize,
|
||||
pub symbols: Vec<Symbol>
|
||||
}
|
||||
|
||||
impl Section {
|
||||
pub fn new(name: String, adr: u64, size: usize) -> Section {
|
||||
Section{name, adr, size, symbols: Vec::new()}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -15,32 +26,8 @@ pub struct Symbol {
|
|||
pub adr: u64,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Fill {
|
||||
pub adr: u64,
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
pub enum Content {
|
||||
Fill(Fill),
|
||||
Section(Section),
|
||||
Symbol(Symbol),
|
||||
}
|
||||
|
||||
impl Section {
|
||||
pub fn new(name: String, adr: Option<u64>, size: Option<usize>, file: Option<String>) -> Section {
|
||||
Section{name, adr, size, file, content: Vec::new()}
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
pub fn new(name: String, adr: u64) -> Symbol {
|
||||
Symbol{name, adr}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fill {
|
||||
pub fn new(adr: u64, size: usize) -> Fill {
|
||||
Fill{adr, size}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue