<commit_before>import core::{vec, str, option};
import option::{some, none};
import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;
import driver::session::session;

enum deref_t { unbox(bool), field, index, }

type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};

// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
// ds=[index,field])
fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
   {ex: @expr, ds: @[deref]} {
    fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
        let ds = [], t = t;
        while true {
            alt ty::struct(tcx, t) {
              ty::ty_box(mt) {
                ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
                t = mt.ty;
              }
              ty::ty_uniq(mt) {
                ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
                t = mt.ty;
              }
              ty::ty_res(_, inner, tps) {
                ds += [@{mut: false, kind: unbox(false), outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, inner);
              }
              ty::ty_enum(did, tps) {
                let variants = ty::enum_variants(tcx, did);
                if vec::len(*variants) != 1u ||
                       vec::len(variants[0].args) != 1u {
                    break;
                }
                ds += [@{mut: false, kind: unbox(false), outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
              }
              _ { break; }
            }
        }
        ret {t: t, ds: ds};
    }
    let ds: [deref] = [], ex = ex;
    while true {
        alt copy ex.node {
          expr_field(base, ident, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            let is_mut = false;
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_rec(fields) {
                for fld: ty::field in fields {
                    if str::eq(ident, fld.ident) {
                        is_mut = fld.mt.mut == mut;
                        break;
                    }
                }
              }
              _ {}
            }
            ds += [@{mut: is_mut, kind: field, outer_t: auto_unbox.t}];
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_index(base, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_vec(mt) {
                ds +=
                    [@{mut: mt.mut == mut,
                       kind: index,
                       outer_t: auto_unbox.t}];
              }
              ty::ty_str {
                ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
              }
              _ {
                  tcx.sess.span_bug(base.span, "Ill-typed base expression in \
                    index");
              }
            }
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_unary(op, base) {
            if op == deref {
                let base_t = ty::expr_ty(tcx, base);
                let is_mut = false, ptr = false;
                alt ty::struct(tcx, base_t) {
                  ty::ty_box(mt) { is_mut = mt.mut == mut; }
                  ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
                  ty::ty_res(_, _, _) { }
                  ty::ty_enum(_, _) { }
                  ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
                  _ { tcx.sess.span_bug(base.span, "Ill-typed base \
                        expression in deref"); }
                }
                ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
                         outer_t: base_t}];
                ex = base;
            } else { break; }
          }
          _ { break; }
        }
    }
    if autoderef {
        let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex));
        ds += auto_unbox.ds;
    }
    ret {ex: ex, ds: @ds};
}

// Actual mut-checking pass

type mut_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt, mut_map: mut_map};

fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map {
    let cx = @{tcx: tcx, mut_map: std::map::new_int_hash()};
    let v = @{visit_expr: bind visit_expr(cx, _, _, _),
              visit_decl: bind visit_decl(cx, _, _, _)
              with *visit::default_visitor()};
    visit::visit_crate(*crate, (), visit::mk_vt(v));
    ret cx.mut_map;
}

enum msg { msg_assign, msg_move_out, msg_mut_ref, }

fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
    cx.tcx.sess.span_err(span, alt msg {
      msg_assign { "assigning to " + name }
      msg_move_out { "moving out of " + name }
      msg_mut_ref { "passing " + name + " by mutable reference" }
    });
}

fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
    visit::visit_decl(d, e, v);
    alt d.node {
      decl_local(locs) {
        for (_, loc) in locs {
            alt loc.node.init {
              some(init) {
                if init.op == init_move { check_move_rhs(cx, init.expr); }
              }
              none { }
            }
        }
      }
      _ { }
    }
}

fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
    alt ex.node {
      expr_call(f, args, _) { check_call(cx, f, args); }
      expr_bind(f, args) { check_bind(cx, f, args); }
      expr_swap(lhs, rhs) {
        check_lval(cx, lhs, msg_assign);
        check_lval(cx, rhs, msg_assign);
      }
      expr_move(dest, src) {
        check_lval(cx, dest, msg_assign);
        check_move_rhs(cx, src);
      }
      expr_assign(dest, src) | expr_assign_op(_, dest, src) {
        check_lval(cx, dest, msg_assign);
      }
      _ { }
    }
    visit::visit_expr(ex, e, v);
}

fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
    alt dest.node {
      expr_path(p) {
        let def = cx.tcx.def_map.get(dest.id);
        alt is_immutable_def(cx, def) {
          some(name) { mk_err(cx, dest.span, msg, name); }
          _ { }
        }
        cx.mut_map.insert(ast_util::def_id_of_def(def).node, ());
      }
      _ {
        let root = expr_root(cx.tcx, dest, false);
        if vec::len(*root.ds) == 0u {
            if msg != msg_move_out {
                mk_err(cx, dest.span, msg, "non-lvalue");
            }
        } else if !root.ds[0].mut {
            let name =
                alt root.ds[0].kind {
                  mut::unbox(_) { "immutable box" }
                  mut::field { "immutable field" }
                  mut::index { "immutable vec content" }
                };
            mk_err(cx, dest.span, msg, name);
        }
      }
    }
}

fn check_move_rhs(cx: @ctx, src: @expr) {
    alt src.node {
      expr_path(p) {
        alt cx.tcx.def_map.get(src.id) {
          def_self(_) {
            mk_err(cx, src.span, msg_move_out, "method self");
          }
          _ { }
        }
        check_lval(cx, src, msg_move_out);
      }
      _ {
        let root = expr_root(cx.tcx, src, false);

        // Not a path and no-derefs means this is a temporary.
        if vec::len(*root.ds) != 0u &&
           root.ds[vec::len(*root.ds) - 1u].kind != unbox(true) {
            cx.tcx.sess.span_err(src.span, "moving out of a data structure");
        }
      }
    }
}

fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg_t: ty::arg in arg_ts {
        alt arg_t.mode {
          by_mut_ref { check_lval(cx, args[i], msg_mut_ref); }
          by_move { check_lval(cx, args[i], msg_move_out); }
          _ {}
        }
        i += 1u;
    }
}

fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg in args {
        alt arg {
          some(expr) {
            alt (alt arg_ts[i].mode {
              by_mut_ref { some("by mutable reference") }
              by_move { some("by move") }
              _ { none }
            }) {
              some(name) {
                cx.tcx.sess.span_err(
                    expr.span, "can not bind an argument passed " + name);
              }
              none {}
            }
          }
          _ {}
        }
        i += 1u;
    }
}

fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
    alt def {
      def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
      def_use(_) {
        some("static item")
      }
      def_arg(_, by_ref) | def_arg(_, by_val) |
      def_arg(_, mode_infer) { some("argument") }
      def_self(_) { some("self argument") }
      def_upvar(_, inner, node_id) {
        let ty = ty::node_id_to_type(cx.tcx, node_id);
        let proto = ty::ty_fn_proto(cx.tcx, ty);
        ret alt proto {
          proto_any | proto_block { is_immutable_def(cx, *inner) }
          _ { some("upvar") }
        };
      }
      def_binding(_) { some("binding") }
      def_local(_, let_ref) { some("by-reference binding") }
      _ { none }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Fix assumption in mut.rs that op overloading breaks<commit_after>import core::{vec, str, option};
import option::{some, none};
import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;
import driver::session::session;

enum deref_t { unbox(bool), field, index, }

type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};

// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
// ds=[index,field])
fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
   {ex: @expr, ds: @[deref]} {
    fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
        let ds = [], t = t;
        while true {
            alt ty::struct(tcx, t) {
              ty::ty_box(mt) {
                ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
                t = mt.ty;
              }
              ty::ty_uniq(mt) {
                ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
                t = mt.ty;
              }
              ty::ty_res(_, inner, tps) {
                ds += [@{mut: false, kind: unbox(false), outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, inner);
              }
              ty::ty_enum(did, tps) {
                let variants = ty::enum_variants(tcx, did);
                if vec::len(*variants) != 1u ||
                       vec::len(variants[0].args) != 1u {
                    break;
                }
                ds += [@{mut: false, kind: unbox(false), outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
              }
              _ { break; }
            }
        }
        ret {t: t, ds: ds};
    }
    let ds: [deref] = [], ex = ex;
    while true {
        alt copy ex.node {
          expr_field(base, ident, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            let is_mut = false;
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_rec(fields) {
                for fld: ty::field in fields {
                    if str::eq(ident, fld.ident) {
                        is_mut = fld.mt.mut == mut;
                        break;
                    }
                }
              }
              _ {}
            }
            ds += [@{mut: is_mut, kind: field, outer_t: auto_unbox.t}];
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_index(base, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_vec(mt) {
                ds +=
                    [@{mut: mt.mut == mut,
                       kind: index,
                       outer_t: auto_unbox.t}];
              }
              ty::ty_str {
                ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
              }
              _ { break; }
            }
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_unary(op, base) {
            if op == deref {
                let base_t = ty::expr_ty(tcx, base);
                let is_mut = false, ptr = false;
                alt ty::struct(tcx, base_t) {
                  ty::ty_box(mt) { is_mut = mt.mut == mut; }
                  ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
                  ty::ty_res(_, _, _) { }
                  ty::ty_enum(_, _) { }
                  ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
                  _ { tcx.sess.span_bug(base.span, "Ill-typed base \
                        expression in deref"); }
                }
                ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
                         outer_t: base_t}];
                ex = base;
            } else { break; }
          }
          _ { break; }
        }
    }
    if autoderef {
        let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex));
        ds += auto_unbox.ds;
    }
    ret {ex: ex, ds: @ds};
}

// Actual mut-checking pass

type mut_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt, mut_map: mut_map};

fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map {
    let cx = @{tcx: tcx, mut_map: std::map::new_int_hash()};
    let v = @{visit_expr: bind visit_expr(cx, _, _, _),
              visit_decl: bind visit_decl(cx, _, _, _)
              with *visit::default_visitor()};
    visit::visit_crate(*crate, (), visit::mk_vt(v));
    ret cx.mut_map;
}

enum msg { msg_assign, msg_move_out, msg_mut_ref, }

fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
    cx.tcx.sess.span_err(span, alt msg {
      msg_assign { "assigning to " + name }
      msg_move_out { "moving out of " + name }
      msg_mut_ref { "passing " + name + " by mutable reference" }
    });
}

fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
    visit::visit_decl(d, e, v);
    alt d.node {
      decl_local(locs) {
        for (_, loc) in locs {
            alt loc.node.init {
              some(init) {
                if init.op == init_move { check_move_rhs(cx, init.expr); }
              }
              none { }
            }
        }
      }
      _ { }
    }
}

fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
    alt ex.node {
      expr_call(f, args, _) { check_call(cx, f, args); }
      expr_bind(f, args) { check_bind(cx, f, args); }
      expr_swap(lhs, rhs) {
        check_lval(cx, lhs, msg_assign);
        check_lval(cx, rhs, msg_assign);
      }
      expr_move(dest, src) {
        check_lval(cx, dest, msg_assign);
        check_move_rhs(cx, src);
      }
      expr_assign(dest, src) | expr_assign_op(_, dest, src) {
        check_lval(cx, dest, msg_assign);
      }
      _ { }
    }
    visit::visit_expr(ex, e, v);
}

fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
    alt dest.node {
      expr_path(p) {
        let def = cx.tcx.def_map.get(dest.id);
        alt is_immutable_def(cx, def) {
          some(name) { mk_err(cx, dest.span, msg, name); }
          _ { }
        }
        cx.mut_map.insert(ast_util::def_id_of_def(def).node, ());
      }
      _ {
        let root = expr_root(cx.tcx, dest, false);
        if vec::len(*root.ds) == 0u {
            if msg != msg_move_out {
                mk_err(cx, dest.span, msg, "non-lvalue");
            }
        } else if !root.ds[0].mut {
            let name =
                alt root.ds[0].kind {
                  mut::unbox(_) { "immutable box" }
                  mut::field { "immutable field" }
                  mut::index { "immutable vec content" }
                };
            mk_err(cx, dest.span, msg, name);
        }
      }
    }
}

fn check_move_rhs(cx: @ctx, src: @expr) {
    alt src.node {
      expr_path(p) {
        alt cx.tcx.def_map.get(src.id) {
          def_self(_) {
            mk_err(cx, src.span, msg_move_out, "method self");
          }
          _ { }
        }
        check_lval(cx, src, msg_move_out);
      }
      _ {
        let root = expr_root(cx.tcx, src, false);

        // Not a path and no-derefs means this is a temporary.
        if vec::len(*root.ds) != 0u &&
           root.ds[vec::len(*root.ds) - 1u].kind != unbox(true) {
            cx.tcx.sess.span_err(src.span, "moving out of a data structure");
        }
      }
    }
}

fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg_t: ty::arg in arg_ts {
        alt arg_t.mode {
          by_mut_ref { check_lval(cx, args[i], msg_mut_ref); }
          by_move { check_lval(cx, args[i], msg_move_out); }
          _ {}
        }
        i += 1u;
    }
}

fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg in args {
        alt arg {
          some(expr) {
            alt (alt arg_ts[i].mode {
              by_mut_ref { some("by mutable reference") }
              by_move { some("by move") }
              _ { none }
            }) {
              some(name) {
                cx.tcx.sess.span_err(
                    expr.span, "can not bind an argument passed " + name);
              }
              none {}
            }
          }
          _ {}
        }
        i += 1u;
    }
}

fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
    alt def {
      def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
      def_use(_) {
        some("static item")
      }
      def_arg(_, by_ref) | def_arg(_, by_val) |
      def_arg(_, mode_infer) { some("argument") }
      def_self(_) { some("self argument") }
      def_upvar(_, inner, node_id) {
        let ty = ty::node_id_to_type(cx.tcx, node_id);
        let proto = ty::ty_fn_proto(cx.tcx, ty);
        ret alt proto {
          proto_any | proto_block { is_immutable_def(cx, *inner) }
          _ { some("upvar") }
        };
      }
      def_binding(_) { some("binding") }
      def_local(_, let_ref) { some("by-reference binding") }
      _ { none }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use crate::architecture::*;
use crate::loader::*;
use crate::memory::backing::Memory;
use crate::memory::MemoryPermissions;
use std::collections::BTreeSet;
use std::fs::File;
use std::io::Read;
use std::path::Path;

/// Loader for a single ELf file.
#[derive(Debug)]
pub struct Elf {
    base_address: u64,
    bytes: Vec<u8>,
    user_function_entries: Vec<u64>,
    architecture: Box<dyn Architecture>,
}

impl Elf {
    /// Create a new Elf from the given bytes. This Elf will be rebased to the given
    /// base address.
    pub fn new(bytes: Vec<u8>, base_address: u64) -> Result<Elf> {
        let architecture = {
            let elf = goblin::elf::Elf::parse(&bytes).map_err(|_| "Not a valid elf")?;

            if elf.header.e_machine == goblin::elf::header::EM_386 {
                Box::new(X86::new())
            } else if elf.header.e_machine == goblin::elf::header::EM_MIPS {
                match elf.header.endianness()? {
                    goblin::container::Endian::Big => {
                        Box::new(Mips::new()) as Box<dyn Architecture>
                    }
                    goblin::container::Endian::Little => {
                        Box::new(Mipsel::new()) as Box<dyn Architecture>
                    }
                }
            } else if elf.header.e_machine == goblin::elf::header::EM_PPC {
                match elf.header.endianness()? {
                    goblin::container::Endian::Big => Box::new(Ppc::new()) as Box<dyn Architecture>,
                    goblin::container::Endian::Little => bail!("PPC Little-Endian not supported"),
                }
            } else if elf.header.e_machine == goblin::elf::header::EM_X86_64 {
                Box::new(Amd64::new())
            } else {
                bail!("Unsupported Architecture");
            }
        };

        Ok(Elf {
            base_address,
            bytes,
            user_function_entries: Vec::new(),
            architecture,
        })
    }

    /// Get the base address of this Elf where it has been loaded into loader
    /// memory.
    pub fn base_address(&self) -> u64 {
        self.base_address
    }

    /// Load an Elf from a file and use the given base address.
    pub fn from_file_with_base_address<P: AsRef<Path>>(
        filename: P,
        base_address: u64,
    ) -> Result<Elf> {
        let filename: &Path = filename.as_ref();
        let mut file = match File::open(filename) {
            Ok(file) => file,
            Err(e) => {
                return Err(format!("Error opening {:?}: {}", filename.to_string_lossy(), e).into())
            }
        };
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        Elf::new(buf, base_address)
    }

    /// Load an elf from a file and use the base address of 0.
    pub fn from_file<P: AsRef<Path>>(filename: P) -> Result<Elf> {
        Elf::from_file_with_base_address(filename, 0)
    }

    /// Allow the user to manually specify a function entry
    pub fn add_user_function(&mut self, address: u64) {
        self.user_function_entries.push(address);
    }

    /// Return the strings from the DT_NEEDED entries.
    pub fn dt_needed(&self) -> Result<Vec<String>> {
        let mut v = Vec::new();

        let elf = self.elf();
        if let Some(dynamic) = elf.dynamic {
            // We need that strtab, and we have to do this one manually.
            // Get the strtab address
            let mut strtab_address = None;
            for dyn_ in &dynamic.dyns {
                if dyn_.d_tag == goblin::elf::dynamic::DT_STRTAB {
                    strtab_address = Some(dyn_.d_val);
                    break;
                }
            }
            if strtab_address.is_none() {
                return Ok(v);
            }
            let strtab_address = strtab_address.unwrap();
            // We're going to make a pretty safe assumption that strtab is all
            // in one section
            for section_header in &elf.section_headers {
                if section_header.sh_addr > 0
                    && section_header.sh_addr <= strtab_address
                    && section_header.sh_addr + section_header.sh_size > strtab_address
                {
                    let start =
                        section_header.sh_offset + (strtab_address - section_header.sh_addr);
                    let size = section_header.sh_size - (start - section_header.sh_offset);
                    let start = start as usize;
                    let size = size as usize;
                    let strtab_bytes = self.bytes.get(start..(start + size)).unwrap();
                    let strtab = goblin::strtab::Strtab::new(&strtab_bytes, 0);
                    for dyn_ in dynamic.dyns {
                        if dyn_.d_tag == goblin::elf::dynamic::DT_NEEDED {
                            let so_name = &strtab[dyn_.d_val as usize];
                            v.push(so_name.to_string());
                        }
                    }
                    return Ok(v);
                }
            }
            // if we got here, we didn't return a vector (I think ;))
            panic!("Failed to get Dynamic strtab");
        }

        Ok(v)
    }

    /// Return the goblin::elf::Elf for this elf.
    pub fn elf(&self) -> goblin::elf::Elf {
        goblin::elf::Elf::parse(&self.bytes).unwrap()
    }

    /// Return all symbols exported from this Elf
    pub fn exported_symbols(&self) -> Vec<Symbol> {
        let mut v = Vec::new();
        let elf = self.elf();
        for sym in elf.dynsyms.iter() {
            if sym.st_value == 0 || sym.st_shndx == 0 {
                continue;
            }
            if sym.st_bind() == goblin::elf::sym::STB_GLOBAL
                || sym.st_bind() == goblin::elf::sym::STB_WEAK
            {
                v.push(Symbol::new(
                    &elf.dynstrtab[sym.st_name],
                    sym.st_value + self.base_address(),
                ));
            }
        }

        v
    }

    /// Return all symbols for this Elf
    pub fn symbols(&self) -> Vec<Symbol> {
        let elf = self.elf();
        let mut symbols = Vec::new();
        for sym in elf.dynsyms.iter() {
            if sym.st_value == 0 {
                continue;
            }
            symbols.push(Symbol::new(
                &elf.dynstrtab[sym.st_name],
                sym.st_value + self.base_address(),
            ));
        }

        for sym in elf.syms.iter() {
            if sym.st_value == 0 {
                continue;
            }
            symbols.push(Symbol::new(
                &elf.strtab[sym.st_name],
                sym.st_value + self.base_address(),
            ));
        }

        for rel in elf.pltrelocs.iter() {
            let sym = match elf.dynsyms.get(rel.r_sym) {
                Some(sym) => sym,
                None => continue,
            };

            let name = &elf.dynstrtab[sym.st_name];
            symbols.push(Symbol::new(name, rel.r_offset));
        }

        symbols.sort();
        symbols.dedup();
        symbols
    }
}

impl Loader for Elf {
    fn memory(&self) -> Result<Memory> {
        let elf = self.elf();
        let mut memory = Memory::new(self.architecture().endian());

        for ph in elf.program_headers {
            if ph.p_type == goblin::elf::program_header::PT_LOAD {
                let file_range = (ph.p_offset as usize)..((ph.p_offset + ph.p_filesz) as usize);
                let mut bytes = self.bytes.get(file_range).ok_or("Malformed Elf")?.to_vec();

                if bytes.len() != ph.p_memsz as usize {
                    bytes.append(&mut vec![0; (ph.p_memsz - ph.p_filesz) as usize]);
                }

                let mut permissions = memory::MemoryPermissions::NONE;
                if ph.p_flags & goblin::elf::program_header::PF_R != 0 {
                    permissions |= MemoryPermissions::READ;
                }
                if ph.p_flags & goblin::elf::program_header::PF_W != 0 {
                    permissions |= MemoryPermissions::WRITE;
                }
                if ph.p_flags & goblin::elf::program_header::PF_X != 0 {
                    permissions |= MemoryPermissions::EXECUTE;
                }

                memory.set_memory(ph.p_vaddr + self.base_address, bytes, permissions);
            }
        }

        Ok(memory)
    }

    fn function_entries(&self) -> Result<Vec<FunctionEntry>> {
        let elf = self.elf();

        let mut function_entries = Vec::new();

        let mut functions_added: BTreeSet<u64> = BTreeSet::new();

        // dynamic symbols
        for sym in &elf.dynsyms {
            if sym.is_function() && sym.st_value != 0 && sym.st_shndx > 0 {
                let name = &elf.dynstrtab[sym.st_name];
                function_entries.push(FunctionEntry::new(
                    sym.st_value + self.base_address,
                    Some(name.to_string()),
                ));
                functions_added.insert(sym.st_value);
            }
        }

        // normal symbols
        for sym in &elf.syms {
            if sym.is_function() && sym.st_value != 0 && sym.st_shndx > 0 {
                let name = &elf.strtab[sym.st_name];
                function_entries.push(FunctionEntry::new(
                    sym.st_value + self.base_address,
                    Some(name.to_string()),
                ));
                functions_added.insert(sym.st_value);
            }
        }

        if !functions_added.contains(&elf.header.e_entry) {
            function_entries.push(FunctionEntry::new(
                elf.header.e_entry + self.base_address,
                None,
            ));
        }

        for user_function_entry in &self.user_function_entries {
            if functions_added
                .get(&(user_function_entry + self.base_address))
                .is_some()
            {
                continue;
            }

            function_entries.push(FunctionEntry::new(
                user_function_entry + self.base_address,
                Some(format!("user_function_{:x}", user_function_entry)),
            ));
        }

        Ok(function_entries)
    }

    fn program_entry(&self) -> u64 {
        self.elf().header.e_entry
    }

    fn architecture(&self) -> &dyn Architecture {
        self.architecture.as_ref()
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn symbols(&self) -> Vec<Symbol> {
        self.symbols()
    }
}
<commit_msg>loader/elf: Avoid duplicated function entries (#95)<commit_after>use crate::architecture::*;
use crate::loader::*;
use crate::memory::backing::Memory;
use crate::memory::MemoryPermissions;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::Read;
use std::path::Path;

/// Loader for a single ELf file.
#[derive(Debug)]
pub struct Elf {
    base_address: u64,
    bytes: Vec<u8>,
    user_function_entries: Vec<u64>,
    architecture: Box<dyn Architecture>,
}

impl Elf {
    /// Create a new Elf from the given bytes. This Elf will be rebased to the given
    /// base address.
    pub fn new(bytes: Vec<u8>, base_address: u64) -> Result<Elf> {
        let architecture = {
            let elf = goblin::elf::Elf::parse(&bytes).map_err(|_| "Not a valid elf")?;

            if elf.header.e_machine == goblin::elf::header::EM_386 {
                Box::new(X86::new())
            } else if elf.header.e_machine == goblin::elf::header::EM_MIPS {
                match elf.header.endianness()? {
                    goblin::container::Endian::Big => {
                        Box::new(Mips::new()) as Box<dyn Architecture>
                    }
                    goblin::container::Endian::Little => {
                        Box::new(Mipsel::new()) as Box<dyn Architecture>
                    }
                }
            } else if elf.header.e_machine == goblin::elf::header::EM_PPC {
                match elf.header.endianness()? {
                    goblin::container::Endian::Big => Box::new(Ppc::new()) as Box<dyn Architecture>,
                    goblin::container::Endian::Little => bail!("PPC Little-Endian not supported"),
                }
            } else if elf.header.e_machine == goblin::elf::header::EM_X86_64 {
                Box::new(Amd64::new())
            } else {
                bail!("Unsupported Architecture");
            }
        };

        Ok(Elf {
            base_address,
            bytes,
            user_function_entries: Vec::new(),
            architecture,
        })
    }

    /// Get the base address of this Elf where it has been loaded into loader
    /// memory.
    pub fn base_address(&self) -> u64 {
        self.base_address
    }

    /// Load an Elf from a file and use the given base address.
    pub fn from_file_with_base_address<P: AsRef<Path>>(
        filename: P,
        base_address: u64,
    ) -> Result<Elf> {
        let filename: &Path = filename.as_ref();
        let mut file = match File::open(filename) {
            Ok(file) => file,
            Err(e) => {
                return Err(format!("Error opening {:?}: {}", filename.to_string_lossy(), e).into())
            }
        };
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        Elf::new(buf, base_address)
    }

    /// Load an elf from a file and use the base address of 0.
    pub fn from_file<P: AsRef<Path>>(filename: P) -> Result<Elf> {
        Elf::from_file_with_base_address(filename, 0)
    }

    /// Allow the user to manually specify a function entry
    pub fn add_user_function(&mut self, address: u64) {
        self.user_function_entries.push(address);
    }

    /// Return the strings from the DT_NEEDED entries.
    pub fn dt_needed(&self) -> Result<Vec<String>> {
        let mut v = Vec::new();

        let elf = self.elf();
        if let Some(dynamic) = elf.dynamic {
            // We need that strtab, and we have to do this one manually.
            // Get the strtab address
            let mut strtab_address = None;
            for dyn_ in &dynamic.dyns {
                if dyn_.d_tag == goblin::elf::dynamic::DT_STRTAB {
                    strtab_address = Some(dyn_.d_val);
                    break;
                }
            }
            if strtab_address.is_none() {
                return Ok(v);
            }
            let strtab_address = strtab_address.unwrap();
            // We're going to make a pretty safe assumption that strtab is all
            // in one section
            for section_header in &elf.section_headers {
                if section_header.sh_addr > 0
                    && section_header.sh_addr <= strtab_address
                    && section_header.sh_addr + section_header.sh_size > strtab_address
                {
                    let start =
                        section_header.sh_offset + (strtab_address - section_header.sh_addr);
                    let size = section_header.sh_size - (start - section_header.sh_offset);
                    let start = start as usize;
                    let size = size as usize;
                    let strtab_bytes = self.bytes.get(start..(start + size)).unwrap();
                    let strtab = goblin::strtab::Strtab::new(&strtab_bytes, 0);
                    for dyn_ in dynamic.dyns {
                        if dyn_.d_tag == goblin::elf::dynamic::DT_NEEDED {
                            let so_name = &strtab[dyn_.d_val as usize];
                            v.push(so_name.to_string());
                        }
                    }
                    return Ok(v);
                }
            }
            // if we got here, we didn't return a vector (I think ;))
            panic!("Failed to get Dynamic strtab");
        }

        Ok(v)
    }

    /// Return the goblin::elf::Elf for this elf.
    pub fn elf(&self) -> goblin::elf::Elf {
        goblin::elf::Elf::parse(&self.bytes).unwrap()
    }

    /// Return all symbols exported from this Elf
    pub fn exported_symbols(&self) -> Vec<Symbol> {
        let mut v = Vec::new();
        let elf = self.elf();
        for sym in elf.dynsyms.iter() {
            if sym.st_value == 0 || sym.st_shndx == 0 {
                continue;
            }
            if sym.st_bind() == goblin::elf::sym::STB_GLOBAL
                || sym.st_bind() == goblin::elf::sym::STB_WEAK
            {
                v.push(Symbol::new(
                    &elf.dynstrtab[sym.st_name],
                    sym.st_value + self.base_address(),
                ));
            }
        }

        v
    }

    /// Return all symbols for this Elf
    pub fn symbols(&self) -> Vec<Symbol> {
        let elf = self.elf();
        let mut symbols = Vec::new();
        for sym in elf.dynsyms.iter() {
            if sym.st_value == 0 {
                continue;
            }
            symbols.push(Symbol::new(
                &elf.dynstrtab[sym.st_name],
                sym.st_value + self.base_address(),
            ));
        }

        for sym in elf.syms.iter() {
            if sym.st_value == 0 {
                continue;
            }
            symbols.push(Symbol::new(
                &elf.strtab[sym.st_name],
                sym.st_value + self.base_address(),
            ));
        }

        for rel in elf.pltrelocs.iter() {
            let sym = match elf.dynsyms.get(rel.r_sym) {
                Some(sym) => sym,
                None => continue,
            };

            let name = &elf.dynstrtab[sym.st_name];
            symbols.push(Symbol::new(name, rel.r_offset));
        }

        symbols.sort();
        symbols.dedup();
        symbols
    }
}

impl Loader for Elf {
    fn memory(&self) -> Result<Memory> {
        let elf = self.elf();
        let mut memory = Memory::new(self.architecture().endian());

        for ph in elf.program_headers {
            if ph.p_type == goblin::elf::program_header::PT_LOAD {
                let file_range = (ph.p_offset as usize)..((ph.p_offset + ph.p_filesz) as usize);
                let mut bytes = self.bytes.get(file_range).ok_or("Malformed Elf")?.to_vec();

                if bytes.len() != ph.p_memsz as usize {
                    bytes.append(&mut vec![0; (ph.p_memsz - ph.p_filesz) as usize]);
                }

                let mut permissions = memory::MemoryPermissions::NONE;
                if ph.p_flags & goblin::elf::program_header::PF_R != 0 {
                    permissions |= MemoryPermissions::READ;
                }
                if ph.p_flags & goblin::elf::program_header::PF_W != 0 {
                    permissions |= MemoryPermissions::WRITE;
                }
                if ph.p_flags & goblin::elf::program_header::PF_X != 0 {
                    permissions |= MemoryPermissions::EXECUTE;
                }

                memory.set_memory(ph.p_vaddr + self.base_address, bytes, permissions);
            }
        }

        Ok(memory)
    }

    fn function_entries(&self) -> Result<Vec<FunctionEntry>> {
        let elf = self.elf();

        let mut function_entries: BTreeMap<u64, FunctionEntry> = BTreeMap::new();

        // dynamic symbols
        for sym in &elf.dynsyms {
            if sym.is_function() && sym.st_value != 0 && sym.st_shndx > 0 {
                let name = &elf.dynstrtab[sym.st_name];
                function_entries.insert(
                    sym.st_value,
                    FunctionEntry::new(sym.st_value + self.base_address, Some(name.to_string())),
                );
            }
        }

        // normal symbols
        for sym in &elf.syms {
            if sym.is_function() && sym.st_value != 0 && sym.st_shndx > 0 {
                let name = &elf.strtab[sym.st_name];
                function_entries.insert(
                    sym.st_value,
                    FunctionEntry::new(sym.st_value + self.base_address, Some(name.to_string())),
                );
            }
        }

        if !function_entries.contains_key(&elf.header.e_entry) {
            function_entries.insert(
                elf.header.e_entry,
                FunctionEntry::new(elf.header.e_entry + self.base_address, None),
            );
        }

        for &user_function_entry in &self.user_function_entries {
            if function_entries.contains_key(&user_function_entry) {
                continue;
            }

            function_entries.insert(
                user_function_entry,
                FunctionEntry::new(
                    user_function_entry + self.base_address,
                    Some(format!("user_function_{:x}", user_function_entry)),
                ),
            );
        }

        Ok(function_entries
            .into_iter()
            .map(|(_, entry)| entry)
            .collect())
    }

    fn program_entry(&self) -> u64 {
        self.elf().header.e_entry
    }

    fn architecture(&self) -> &dyn Architecture {
        self.architecture.as_ref()
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn symbols(&self) -> Vec<Symbol> {
        self.symbols()
    }
}
<|endoftext|>


<commit_before>use cgmath::Point2;
use crossbeam_channel as channel;
use specs;
use specs::prelude::{Read, ReadStorage, WriteStorage};

use crate::bullet::bullets::Bullets;
use crate::character::{CharacterDrawable, controls::CharacterInputState};
use crate::graphics::{camera::CameraInputState, dimensions::Dimensions, direction, direction_movement};
use crate::shaders::Position;

type MouseEvent = channel::Sender<(MouseControl, Option<(f64, f64)>)>;

#[derive(Clone)]
pub struct MouseInputState {
  pub mouse_left: Option<Point2<f32>>,
  pub mouse_right: Option<Point2<f32>>,
  pub left_click_point: Option<Point2<f32>>,
  pub right_click_point: Option<Point2<f32>>,
}

impl MouseInputState {
  pub fn new() -> MouseInputState {
    MouseInputState {
      mouse_left: None,
      mouse_right: None,
      left_click_point: None,
      right_click_point: None,
    }
  }
}

impl Default for MouseInputState {
  fn default() -> MouseInputState {
    MouseInputState::new()
  }
}

impl specs::prelude::Component for MouseInputState {
  type Storage = specs::storage::VecStorage<MouseInputState>;
}

pub enum MouseControl {
  LeftClick,
  RightClick,
}

pub struct MouseControlSystem {
  queue: channel::Receiver<(MouseControl, Option<(f64, f64)>)>,
}

impl MouseControlSystem {
  pub fn new() -> (MouseControlSystem, MouseEvent) {
    let (tx, rx) = channel::unbounded();
    (MouseControlSystem {
      queue: rx,
    }, tx)
  }
}

impl<'a> specs::prelude::System<'a> for MouseControlSystem {
  type SystemData = (WriteStorage<'a, MouseInputState>,
                     WriteStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     WriteStorage<'a, Bullets>,
                     Read<'a, Dimensions>);

  fn run(&mut self, (mut mouse_input, mut character_drawable, camera, character_input, mut bullets, dim): Self::SystemData) {
    use specs::join::Join;

    while let Ok((control_value, value)) = self.queue.try_recv() {
      match control_value {
        MouseControl::LeftClick => {
          for (mi, cd, bs, ca, ci) in (&mut mouse_input, &mut character_drawable, &mut bullets, &camera, &character_input).join() {
            if let Some(val) = value {
              if ci.is_shooting && cd.stats.ammunition > 0 {
                cd.stats.ammunition -= 1;
                let start_point = Point2::new(dim.window_width / 2.0 * dim.hidpi_factor, dim.window_height / 2.0 * dim.hidpi_factor);
                let end_point = Point2::new(val.0 as f32, val.1 as f32);
                mi.left_click_point = Some(end_point);
                let movement_direction = direction_movement(direction(start_point, end_point));
                Bullets::add_bullet(bs, Position::new(-ca.movement.x(), ca.movement.y()), movement_direction);
              }
            } else {
              mi.left_click_point = None;
            }
          }
        }
        MouseControl::RightClick => {
          for mi in (&mut mouse_input).join() {
            if let Some(val) = value {
              mi.right_click_point = Some(Point2::new(val.0 as f32, val.1 as f32));
            } else {
              mi.right_click_point = None
            }
          }
        }
      }
    }
  }
}
<commit_msg>Fix mouse click coordinate <commit_after>use cgmath::Point2;
use crossbeam_channel as channel;
use specs;
use specs::prelude::{Read, ReadStorage, WriteStorage};

use crate::bullet::bullets::Bullets;
use crate::character::{CharacterDrawable, controls::CharacterInputState};
use crate::graphics::{camera::CameraInputState, dimensions::Dimensions, direction, direction_movement};
use crate::shaders::Position;

type MouseEvent = channel::Sender<(MouseControl, Option<(f64, f64)>)>;

#[derive(Clone)]
pub struct MouseInputState {
  pub mouse_left: Option<Point2<f32>>,
  pub mouse_right: Option<Point2<f32>>,
  pub left_click_point: Option<Point2<f32>>,
  pub right_click_point: Option<Point2<f32>>,
}

impl MouseInputState {
  pub fn new() -> MouseInputState {
    MouseInputState {
      mouse_left: None,
      mouse_right: None,
      left_click_point: None,
      right_click_point: None,
    }
  }
}

impl Default for MouseInputState {
  fn default() -> MouseInputState {
    MouseInputState::new()
  }
}

impl specs::prelude::Component for MouseInputState {
  type Storage = specs::storage::VecStorage<MouseInputState>;
}

pub enum MouseControl {
  LeftClick,
  RightClick,
}

pub struct MouseControlSystem {
  queue: channel::Receiver<(MouseControl, Option<(f64, f64)>)>,
}

impl MouseControlSystem {
  pub fn new() -> (MouseControlSystem, MouseEvent) {
    let (tx, rx) = channel::unbounded();
    (MouseControlSystem {
      queue: rx,
    }, tx)
  }
}

impl<'a> specs::prelude::System<'a> for MouseControlSystem {
  type SystemData = (WriteStorage<'a, MouseInputState>,
                     WriteStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     WriteStorage<'a, Bullets>,
                     Read<'a, Dimensions>);

  fn run(&mut self, (mut mouse_input, mut character_drawable, camera, character_input, mut bullets, dim): Self::SystemData) {
    use specs::join::Join;

    while let Ok((control_value, value)) = self.queue.try_recv() {
      match control_value {
        MouseControl::LeftClick => {
          for (mut mi, cd, bs, ca, ci) in (&mut mouse_input, &mut character_drawable, &mut bullets, &camera, &character_input).join() {
            if let Some(val) = value {
              if ci.is_shooting && cd.stats.ammunition > 0 {
                cd.stats.ammunition -= 1;
                let start_point = Point2::new(dim.window_width / 2.0 * dim.hidpi_factor, dim.window_height / 2.0 * dim.hidpi_factor);
                let end_point = Point2::new(val.0 as f32 * dim.hidpi_factor, val.1 as f32 * dim.hidpi_factor);
                mi.left_click_point = Some(end_point);
                let movement_direction = direction_movement(direction(start_point, end_point));
                Bullets::add_bullet(bs, Position::new(-ca.movement.x(), ca.movement.y()), movement_direction);
              }
            } else {
              mi.left_click_point = None;
            }
          }
        }
        MouseControl::RightClick => {
          for mi in (&mut mouse_input).join() {
            if let Some(val) = value {
              mi.right_click_point = Some(Point2::new(val.0 as f32, val.1 as f32));
            } else {
              mi.right_click_point = None
            }
          }
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>use anyhow::Result;
use byteorder::{ByteOrder, LittleEndian};

use crate::{
    pagemap::{PageMap, PageMapError},
    RVA, VA,
};

pub trait AddressSpace<T> {
    fn read_into(&self, offset: T, buf: &mut [u8]) -> Result<()>;

    fn read_u8(&self, offset: T) -> Result<u8> {
        let mut buf = [0u8; 1];
        self.read_into(offset, &mut buf)?;
        Ok(buf[0])
    }

    fn read_u16(&self, offset: T) -> Result<u16> {
        let mut buf = [0u8; 2];
        self.read_into(offset, &mut buf)?;
        Ok(LittleEndian::read_u16(&buf))
    }

    fn read_u32(&self, offset: T) -> Result<u32> {
        let mut buf = [0u8; 4];
        self.read_into(offset, &mut buf)?;
        Ok(LittleEndian::read_u32(&buf))
    }

    fn read_u64(&self, offset: T) -> Result<u64> {
        let mut buf = [0u8; 8];
        self.read_into(offset, &mut buf)?;
        Ok(LittleEndian::read_u64(&buf))
    }

    // TODO: rename read_bytes
    fn read_buf(&self, offset: T, length: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; length];
        self.read_into(offset, &mut buf)?;
        Ok(buf)
    }
}

/// An AddressSpace in which data is mapped at or near after a base address,
/// and addressed using positive offsets from this base address.
///
/// For example, this is appropriate for a PE file loaded into memory, using
/// pointers relative to the preferred base address. Here, OEP might be 0x1000.
///
/// Note that this implements `AddressSpace<RVA>` and not `AddressSpace<VA>`.
/// Use `AbsoluteAddressSpace` when you're dealing with absolute addresses
/// (`VA`).
#[derive(Clone)]
pub struct RelativeAddressSpace {
    pub(crate) map: PageMap<u8>,
}

impl RelativeAddressSpace {
    pub fn into_absolute(self, base_address: VA) -> Result<AbsoluteAddressSpace> {
        Ok(AbsoluteAddressSpace {
            base_address,
            relative: self,
        })
    }

    pub fn with_capacity(size: u64) -> RelativeAddressSpace {
        RelativeAddressSpace {
            map: PageMap::with_capacity(size),
        }
    }
}

impl AddressSpace<RVA> for RelativeAddressSpace {
    fn read_into(&self, offset: RVA, buf: &mut [u8]) -> Result<()> {
        self.map.slice_into(offset, buf)?;
        Ok(())
    }
}

/// An AddressSpace in which (mostly) contiguous data is mapped at a base
/// address, is addressed using absolute pointers (relative to 0x0).
///
/// For example, this is appropriate for a PE file loaded into memory at its
/// preferred base address, using pointers relative to 0x0. Here, OEP might be
/// 0x401000.
///
/// Internally, this is a `RelativeAddressSpace` + a base address.
/// So, its not a good fit for multiple modules that may be mapped different
/// places. Probably want to implement `SparseAddressSpace` (collection of
/// `AbsoluteAddressSpace`s)  for this.
///
/// Note that this implements `AddressSpace<VA>` and not `AddressSpace<RVA>`.
/// Use `RelativeAddressSpace` when you're dealing with relative addresses
/// (`RVA`).
#[derive(Clone)]
pub struct AbsoluteAddressSpace {
    pub base_address: VA,

    /// The inner relative address space with data mapped at `base_address`.
    /// Its ok to reach into this address space if you've got RVAs relative to
    /// `base_address`.
    pub relative: RelativeAddressSpace,
}

impl AddressSpace<VA> for AbsoluteAddressSpace {
    fn read_into(&self, offset: VA, buf: &mut [u8]) -> Result<()> {
        if offset < self.base_address {
            return Err(PageMapError::NotMapped.into());
        }

        self.relative.read_into((offset - self.base_address) as RVA, buf)
    }
}
<commit_msg>address space: add read_ascii<commit_after>use anyhow::Result;
use byteorder::{ByteOrder, LittleEndian};

use crate::{
    pagemap::{PageMap, PageMapError},
    RVA, VA,
};

pub trait AddressSpace<T> {
    fn read_into(&self, offset: T, buf: &mut [u8]) -> Result<()>;

    fn read_u8(&self, offset: T) -> Result<u8> {
        let mut buf = [0u8; 1];
        self.read_into(offset, &mut buf)?;
        Ok(buf[0])
    }

    fn read_u16(&self, offset: T) -> Result<u16> {
        let mut buf = [0u8; 2];
        self.read_into(offset, &mut buf)?;
        Ok(LittleEndian::read_u16(&buf))
    }

    fn read_u32(&self, offset: T) -> Result<u32> {
        let mut buf = [0u8; 4];
        self.read_into(offset, &mut buf)?;
        Ok(LittleEndian::read_u32(&buf))
    }

    fn read_u64(&self, offset: T) -> Result<u64> {
        let mut buf = [0u8; 8];
        self.read_into(offset, &mut buf)?;
        Ok(LittleEndian::read_u64(&buf))
    }

    // TODO: rename read_bytes
    fn read_buf(&self, offset: T, length: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; length];
        self.read_into(offset, &mut buf)?;
        Ok(buf)
    }

    /// Read a NULL-terminated, ASCII-encoded string at the given offset.
    ///
    /// Errors:
    ///
    ///   - PageMapError - if the address is not mapped.
    ///   - std::str::from_utf8 errors - if the data is not valid utf8
    ///
    fn read_ascii(&self, offset: T) -> Result<String>;
}

/// An AddressSpace in which data is mapped at or near after a base address,
/// and addressed using positive offsets from this base address.
///
/// For example, this is appropriate for a PE file loaded into memory, using
/// pointers relative to the preferred base address. Here, OEP might be 0x1000.
///
/// Note that this implements `AddressSpace<RVA>` and not `AddressSpace<VA>`.
/// Use `AbsoluteAddressSpace` when you're dealing with absolute addresses
/// (`VA`).
#[derive(Clone)]
pub struct RelativeAddressSpace {
    pub(crate) map: PageMap<u8>,
}

impl RelativeAddressSpace {
    pub fn into_absolute(self, base_address: VA) -> Result<AbsoluteAddressSpace> {
        Ok(AbsoluteAddressSpace {
            base_address,
            relative: self,
        })
    }

    pub fn with_capacity(size: u64) -> RelativeAddressSpace {
        RelativeAddressSpace {
            map: PageMap::with_capacity(size),
        }
    }
}

impl AddressSpace<RVA> for RelativeAddressSpace {
    fn read_into(&self, offset: RVA, buf: &mut [u8]) -> Result<()> {
        self.map.slice_into(offset, buf)?;
        Ok(())
    }

    fn read_ascii(&self, offset: RVA) -> Result<String> {
        let buf: Vec<u8> = (offset..std::u64::MAX)
            .map(|offset| self.map.get(offset))
            .take_while(|c| c.is_some())
            .map(|c| c.unwrap())
            .take_while(|&c| c != 0)
            .collect();

        Ok(String::from_utf8(buf)?)
    }
}

/// An AddressSpace in which (mostly) contiguous data is mapped at a base
/// address, is addressed using absolute pointers (relative to 0x0).
///
/// For example, this is appropriate for a PE file loaded into memory at its
/// preferred base address, using pointers relative to 0x0. Here, OEP might be
/// 0x401000.
///
/// Internally, this is a `RelativeAddressSpace` + a base address.
/// So, its not a good fit for multiple modules that may be mapped different
/// places. Probably want to implement `SparseAddressSpace` (collection of
/// `AbsoluteAddressSpace`s)  for this.
///
/// Note that this implements `AddressSpace<VA>` and not `AddressSpace<RVA>`.
/// Use `RelativeAddressSpace` when you're dealing with relative addresses
/// (`RVA`).
#[derive(Clone)]
pub struct AbsoluteAddressSpace {
    pub base_address: VA,

    /// The inner relative address space with data mapped at `base_address`.
    /// Its ok to reach into this address space if you've got RVAs relative to
    /// `base_address`.
    pub relative: RelativeAddressSpace,
}

impl AddressSpace<VA> for AbsoluteAddressSpace {
    fn read_into(&self, offset: VA, buf: &mut [u8]) -> Result<()> {
        if offset < self.base_address {
            return Err(PageMapError::NotMapped.into());
        }

        self.relative.read_into((offset - self.base_address) as RVA, buf)
    }

    fn read_ascii(&self, offset: VA) -> Result<String> {
        if offset < self.base_address {
            return Err(PageMapError::NotMapped.into());
        }

        self.relative.read_ascii((offset - self.base_address) as RVA)
    }
}
<|endoftext|>


<commit_before>/// The `mutate` trait returns a mutation version of a type that implements it.
///
/// Implementer should try to create persisted data-structures

extern crate rand;

use self::rand::Rng;
use super::super::structure::{Program,Condition,Expression,Sensor,Command};

pub trait Mutate {
    fn mutate(&self) -> Self;
}

enum MutateType {
    ThisLevel,
    NextLevel,
}

impl rand::Rand for MutateType {
    fn rand<R: rand::Rng>(_: &mut R) -> Self {
        pick![
            1, MutateType::ThisLevel,
            1, MutateType::NextLevel
        ]
    }
}

impl Mutate for Program {
    fn mutate(&self) -> Program {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                match *self {
                    _ => {
                        let mutation: Program = rand::random();
                        mutation
                    }
                }
            },
            MutateType::NextLevel => {
                match *self {
                    Program::If(ref condition, ref left, ref right) => {
                        let mut rng = rand::thread_rng();
                        match rng.gen_range(0, 3) {
                            0 => { /* mutate condition */
                                      let mutation: Condition = condition.mutate();
                                      Program::If(mutation, left.clone(), right.clone())
                            },
                            1 => { /* mutate left */
                                      let mutation: Program = left.mutate();
                                      Program::If(condition.clone(), Box::new(mutation), right.clone())
                            },
                            2 => { /* mutate right */
                                      let mutation: Program = right.mutate();
                                      Program::If(condition.clone(), left.clone(), Box::new(mutation))
                            },
                            _ => { panic!(/* this should not happen */)},
                        }
                    },
                    Program::Command(ref command) => {
                        let mutation: Command = command.mutate();
                        Program::Command(mutation)
                    }
                }
            },
        }
    }
}

impl Mutate for Condition {
    fn mutate(&self) -> Condition {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                match *self {
                    _ => {
                        let mutation: Condition = rand::random();
                        mutation
                    },
                }
            },
            MutateType::NextLevel => {
                match *self {
                    Condition::True => Condition::False,
                    Condition::False => Condition::True,
                    Condition::Not(ref condition) => {
                        let mutation: Condition = condition.mutate();
                        Condition::Not(Box::new(mutation))
                    },
                    Condition::Or(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate();
                            Condition::Or(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate();
                            Condition::Or(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::And(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate();
                            Condition::And(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate();
                            Condition::And(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Less(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Less(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Less(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::LessEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::LessEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::LessEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Equal(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Equal(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Equal(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::GreaterEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::GreaterEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::GreaterEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Greater(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Greater(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Greater(left.clone(), Box::new(mutation))
                        }
                    }
                }
            }
        }
    }
}

impl Mutate for Expression {
    fn mutate(&self) -> Expression {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                match *self {
                    _ => {
                        let mutation: Expression = rand::random();
                        mutation
                    },
                }
            },
            MutateType::NextLevel => {
                match *self {
                    Expression::Constant(_) => {
                        let mutation: f32 = rand::random();
                        Expression::Constant(mutation)
                    },
                    Expression::Sensor(ref sensor) => {
                        let mutation: Sensor = sensor.mutate();
                        Expression::Sensor(mutation)
                    },
                    Expression::Plus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Plus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Plus(left.clone(),Box::new(mutation))
                        }
                    },
                    Expression::Minus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Minus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Minus(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Multiply(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Multiply(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Multiply(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Divide(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Divide(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Divide(left.clone(), Box::new(mutation))
                        }
                    },
                }
            }
        }
    }
}

impl Mutate for Sensor {
    fn mutate(&self) -> Sensor {
        let mutation: Sensor = rand::random();
        mutation
    }
}

impl Mutate for Command {
    fn mutate(&self) -> Command {
        let mutation: Command = rand::random();
        mutation
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use structure::{Expression,Sensor};

    #[derive(PartialEq,Debug)]
    enum Dummy {
        A, B,
    }

    impl super::Mutate for Dummy {
        fn mutate(&self) -> Dummy {
            match *self {
                Dummy::A => Dummy::B,
                Dummy::B => Dummy::A
            }
        }
    }

    #[test]
    fn should_mutate_mutate_dummy() {
        let original = Dummy::A;

        let mutation = original.mutate();

        assert_eq!(mutation, Dummy::B);
    }

    #[test]
    fn should_mutate_expression_without_panicing() {
        let constant: Expression = Expression::Constant(0.0);
        constant.mutate();

        let sensor: Expression = Expression::Sensor(Sensor::Vx);
        sensor.mutate();

    }
}
<commit_msg>Return random structure for ThisLevel mutation<commit_after>/// The `mutate` trait returns a mutation version of a type that implements it.
///
/// Implementer should try to create persisted data-structures

extern crate rand;

use self::rand::Rng;
use super::super::structure::{Program,Condition,Expression,Sensor,Command};

pub trait Mutate {
    fn mutate(&self) -> Self;
}

enum MutateType {
    ThisLevel,
    NextLevel,
}

impl rand::Rand for MutateType {
    fn rand<R: rand::Rng>(_: &mut R) -> Self {
        pick![
            1, MutateType::ThisLevel,
            1, MutateType::NextLevel
        ]
    }
}

impl Mutate for Program {
    fn mutate(&self) -> Program {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Program = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Program::If(ref condition, ref left, ref right) => {
                        let mut rng = rand::thread_rng();
                        match rng.gen_range(0, 3) {
                            0 => { /* mutate condition */
                                      let mutation: Condition = condition.mutate();
                                      Program::If(mutation, left.clone(), right.clone())
                            },
                            1 => { /* mutate left */
                                      let mutation: Program = left.mutate();
                                      Program::If(condition.clone(), Box::new(mutation), right.clone())
                            },
                            2 => { /* mutate right */
                                      let mutation: Program = right.mutate();
                                      Program::If(condition.clone(), left.clone(), Box::new(mutation))
                            },
                            _ => { panic!(/* this should not happen */)},
                        }
                    },
                    Program::Command(ref command) => {
                        let mutation: Command = command.mutate();
                        Program::Command(mutation)
                    }
                }
            },
        }
    }
}

impl Mutate for Condition {
    fn mutate(&self) -> Condition {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Condition = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Condition::True => Condition::False,
                    Condition::False => Condition::True,
                    Condition::Not(ref condition) => {
                        let mutation: Condition = condition.mutate();
                        Condition::Not(Box::new(mutation))
                    },
                    Condition::Or(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate();
                            Condition::Or(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate();
                            Condition::Or(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::And(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Condition = left.mutate();
                            Condition::And(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Condition = right.mutate();
                            Condition::And(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Less(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Less(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Less(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::LessEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::LessEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::LessEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Equal(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Equal(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Equal(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::GreaterEqual(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::GreaterEqual(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::GreaterEqual(left.clone(), Box::new(mutation))
                        }
                    },
                    Condition::Greater(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Condition::Greater(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Condition::Greater(left.clone(), Box::new(mutation))
                        }
                    }
                }
            }
        }
    }
}

impl Mutate for Expression {
    fn mutate(&self) -> Expression {
        let mutate_type: MutateType = rand::random();
        match mutate_type {
            MutateType::ThisLevel => {
                let mutation: Expression = rand::random();
                mutation
            },
            MutateType::NextLevel => {
                match *self {
                    Expression::Constant(_) => {
                        let mutation: f32 = rand::random();
                        Expression::Constant(mutation)
                    },
                    Expression::Sensor(ref sensor) => {
                        let mutation: Sensor = sensor.mutate();
                        Expression::Sensor(mutation)
                    },
                    Expression::Plus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Plus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Plus(left.clone(),Box::new(mutation))
                        }
                    },
                    Expression::Minus(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Minus(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Minus(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Multiply(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Multiply(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Multiply(left.clone(), Box::new(mutation))
                        }
                    },
                    Expression::Divide(ref left, ref right) => {
                        let mutate_left: bool = rand::random();
                        if mutate_left {
                            let mutation: Expression = left.mutate();
                            Expression::Divide(Box::new(mutation), right.clone())
                        } else {
                            let mutation: Expression = right.mutate();
                            Expression::Divide(left.clone(), Box::new(mutation))
                        }
                    },
                }
            }
        }
    }
}

impl Mutate for Sensor {
    fn mutate(&self) -> Sensor {
        let mutation: Sensor = rand::random();
        mutation
    }
}

impl Mutate for Command {
    fn mutate(&self) -> Command {
        let mutation: Command = rand::random();
        mutation
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use structure::{Expression,Sensor};

    #[derive(PartialEq,Debug)]
    enum Dummy {
        A, B,
    }

    impl super::Mutate for Dummy {
        fn mutate(&self) -> Dummy {
            match *self {
                Dummy::A => Dummy::B,
                Dummy::B => Dummy::A
            }
        }
    }

    #[test]
    fn should_mutate_mutate_dummy() {
        let original = Dummy::A;

        let mutation = original.mutate();

        assert_eq!(mutation, Dummy::B);
    }

    #[test]
    fn should_mutate_expression_without_panicing() {
        let constant: Expression = Expression::Constant(0.0);
        constant.mutate();

        let sensor: Expression = Expression::Sensor(Sensor::Vx);
        sensor.mutate();
    }
}
<|endoftext|>