missing symbol filling
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
use super::program::Addr;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ELF64Header {
|
pub struct ELF64Header {
|
||||||
magic: u32,
|
magic: u32,
|
||||||
@@ -49,7 +51,7 @@ pub struct SectionHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this is currently specialized for riscv64; obviously add params later
|
// this is currently specialized for riscv64; obviously add params later
|
||||||
pub fn create(program: Vec<u8>, start_offset: u64) -> Vec<u8> {
|
pub fn create(program: Vec<u8>, start_offset: Addr) -> Vec<u8> {
|
||||||
let addr_start = 0x1000;
|
let addr_start = 0x1000;
|
||||||
let page_size = 0x1000;
|
let page_size = 0x1000;
|
||||||
let progam_size = std::mem::size_of_val(&program[..]) as u64;
|
let progam_size = std::mem::size_of_val(&program[..]) as u64;
|
||||||
@@ -76,7 +78,7 @@ pub fn create(program: Vec<u8>, start_offset: u64) -> Vec<u8> {
|
|||||||
ty: 0x2, // executable
|
ty: 0x2, // executable
|
||||||
machine: 0xf3, // risc-v
|
machine: 0xf3, // risc-v
|
||||||
e_version: 0x1,
|
e_version: 0x1,
|
||||||
entry: addr_start + program_pos + start_offset,
|
entry: addr_start + program_pos + start_offset.val(),
|
||||||
program_header_offset: size_of::<ELF64Header>() as u64,
|
program_header_offset: size_of::<ELF64Header>() as u64,
|
||||||
section_header_offset: 0x0,
|
section_header_offset: 0x0,
|
||||||
// C ABI (16 bit instruction align) + double precision floats
|
// C ABI (16 bit instruction align) + double precision floats
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ mod program;
|
|||||||
mod riscv64;
|
mod riscv64;
|
||||||
mod target;
|
mod target;
|
||||||
|
|
||||||
|
use program::*;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
let dir = Path::new("./build");
|
let dir = Path::new("./build");
|
||||||
@@ -62,7 +64,3 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// qemu-riscv64 -g 1234 test &
|
|
||||||
// riscv64-linux-gnu-gdb -q \
|
|
||||||
// -ex "target remote :1234" \
|
|
||||||
// test
|
|
||||||
|
|||||||
@@ -1,35 +1,118 @@
|
|||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, ops::Deref};
|
||||||
|
|
||||||
pub fn create_program<I: Instr>(
|
pub fn create_program<I: Instr>(map: SymMap<I>, start: Symbol) -> (Vec<u8>, Option<Addr>) {
|
||||||
ro_data: HashMap<String, Vec<u8>>,
|
|
||||||
functions: Vec<Function<I>>,
|
|
||||||
) -> (Vec<u8>, Option<u64>) {
|
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
let mut sym_map = HashMap::new();
|
let mut sym_table = SymTable::new(map.len());
|
||||||
for (key, val) in ro_data {
|
let mut missing = HashMap::<Symbol, Vec<(Addr, I)>>::new();
|
||||||
sym_map.insert(key, data.len() as u64);
|
for (val, id) in map.ro_data {
|
||||||
|
sym_table.insert(id, Addr(data.len() as u64));
|
||||||
data.extend(val);
|
data.extend(val);
|
||||||
}
|
}
|
||||||
let mut start = None;
|
for (fun, id) in map.functions {
|
||||||
for fun in functions {
|
sym_table.insert(id, Addr(data.len() as u64));
|
||||||
if fun.label == "_start" {
|
for i in fun {
|
||||||
start = Some(data.len() as u64);
|
let i_pos = Addr(data.len() as u64);
|
||||||
}
|
if let Some(sym) = i.push(&mut data, &sym_table, i_pos, false) {
|
||||||
sym_map.insert(fun.label, data.len() as u64);
|
if let Some(vec) = missing.get_mut(&sym) {
|
||||||
for i in fun.instructions {
|
vec.push((i_pos, i));
|
||||||
let pos = data.len() as u64;
|
} else {
|
||||||
i.push(&mut data, &sym_map, pos);
|
missing.insert(sym, vec![(i_pos, i)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(data, start)
|
|
||||||
}
|
}
|
||||||
|
if let Some(vec) = missing.remove(&id) {
|
||||||
pub struct Function<I: Instr> {
|
for (addr, i) in vec {
|
||||||
pub label: String,
|
let mut replace = Vec::new();
|
||||||
pub instructions: Vec<I>,
|
i.push(&mut replace, &sym_table, addr, true);
|
||||||
|
let pos = addr.val() as usize;
|
||||||
|
data[pos..pos + replace.len()].copy_from_slice(&replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(missing.is_empty());
|
||||||
|
(data, sym_table.get(start))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instr {
|
pub trait Instr {
|
||||||
fn push(&self, data: &mut Vec<u8>, ro_map: &HashMap<String, u64>, pos: u64) -> Option<String>;
|
fn push(&self, data: &mut Vec<u8>, syms: &SymTable, pos: Addr, missing: bool) -> Option<Symbol>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub struct Addr(u64);
|
||||||
|
impl Addr {
|
||||||
|
const NONE: Self = Self(!0);
|
||||||
|
pub fn val(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
pub struct Symbol(usize);
|
||||||
|
/// intentionally does not have copy or clone;
|
||||||
|
/// this should only be consumed once
|
||||||
|
pub struct WritableSymbol(Symbol);
|
||||||
|
|
||||||
|
impl Deref for WritableSymbol {
|
||||||
|
type Target = Symbol;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SymMap<I: Instr> {
|
||||||
|
i: usize,
|
||||||
|
ro_data: Vec<(Vec<u8>, Symbol)>,
|
||||||
|
functions: Vec<(Vec<I>, Symbol)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Instr> SymMap<I> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
i: 0,
|
||||||
|
ro_data: Vec::new(),
|
||||||
|
functions: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn push_ro_data(&mut self, data: impl Into<Vec<u8>>) -> (Symbol, usize) {
|
||||||
|
let sym = self.reserve();
|
||||||
|
self.write_ro_data(sym, data)
|
||||||
|
}
|
||||||
|
pub fn push_fn(&mut self, instructions: Vec<I>) -> Symbol {
|
||||||
|
let sym = self.reserve();
|
||||||
|
self.write_fn(sym, instructions)
|
||||||
|
}
|
||||||
|
pub fn write_ro_data(&mut self, sym: WritableSymbol, data: impl Into<Vec<u8>>) -> (Symbol, usize) {
|
||||||
|
let data = data.into();
|
||||||
|
let len = data.len();
|
||||||
|
self.ro_data.push((data, *sym));
|
||||||
|
(*sym, len)
|
||||||
|
}
|
||||||
|
pub fn write_fn(&mut self, sym: WritableSymbol, instructions: Vec<I>) -> Symbol {
|
||||||
|
self.functions.push((instructions, *sym));
|
||||||
|
*sym
|
||||||
|
}
|
||||||
|
pub fn reserve(&mut self) -> WritableSymbol {
|
||||||
|
let val = self.i;
|
||||||
|
self.i += 1;
|
||||||
|
WritableSymbol(Symbol(val))
|
||||||
|
}
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.functions.len() + self.ro_data.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SymTable(Vec<Addr>);
|
||||||
|
impl SymTable {
|
||||||
|
pub fn new(len: usize) -> Self {
|
||||||
|
Self(vec![Addr::NONE; len])
|
||||||
|
}
|
||||||
|
pub fn insert(&mut self, sym: Symbol, addr: Addr) {
|
||||||
|
self.0[sym.0] = addr;
|
||||||
|
}
|
||||||
|
pub fn get(&self, sym: Symbol) -> Option<Addr> {
|
||||||
|
match self.0[sym.0] {
|
||||||
|
Addr::NONE => None,
|
||||||
|
addr => Some(addr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,57 +1,56 @@
|
|||||||
use crate::compiler::program::Instr;
|
use crate::compiler::program::{Addr, Instr, SymTable, Symbol};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub enum AsmInstruction {
|
pub enum AsmInstruction {
|
||||||
Addi(Reg, Reg, i32),
|
Addi(Reg, Reg, i32),
|
||||||
La(Reg, String),
|
La(Reg, Symbol),
|
||||||
Jal(Reg, i32),
|
Jal(Reg, i32),
|
||||||
Jala(String),
|
Call(Symbol),
|
||||||
Ja(String),
|
J(Symbol),
|
||||||
Ret,
|
Ret,
|
||||||
Ecall,
|
Ecall,
|
||||||
|
Li(Reg, i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instr for AsmInstruction {
|
impl Instr for AsmInstruction {
|
||||||
fn push(
|
fn push(&self, data: &mut Vec<u8>, sym_map: &SymTable, pos: Addr, missing: bool) -> Option<Symbol> {
|
||||||
&self,
|
let last = match self {
|
||||||
data: &mut Vec<u8>,
|
Self::Addi(dest, src, imm) => addi(*dest, *src, BitsI32::new(*imm)),
|
||||||
sym_map: &std::collections::HashMap<String, u64>,
|
|
||||||
pos: u64,
|
|
||||||
) -> Option<String> {
|
|
||||||
match self {
|
|
||||||
Self::Addi(dest, src, imm) => {
|
|
||||||
data.extend(addi(*dest, *src, BitsI32::new(*imm)).to_le_bytes());
|
|
||||||
}
|
|
||||||
Self::La(dest, sym) => {
|
Self::La(dest, sym) => {
|
||||||
if let Some(addr) = sym_map.get(sym) {
|
if let Some(addr) = sym_map.get(*sym) {
|
||||||
let offset = *addr as i32 - pos as i32;
|
let offset = addr.val() as i32 - pos.val() as i32;
|
||||||
data.extend(auipc(*dest, BitsI32::new(0)).to_le_bytes());
|
data.extend(auipc(*dest, BitsI32::new(0)).to_le_bytes());
|
||||||
data.extend(addi(*dest, *dest, BitsI32::new(offset)).to_le_bytes());
|
addi(*dest, *dest, BitsI32::new(offset))
|
||||||
} else {
|
} else {
|
||||||
return Some(sym.to_string());
|
data.extend_from_slice(&[0; 2 * 4]);
|
||||||
|
return Some(*sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Jal(dest, offset) => data.extend(jal(*dest, BitsI32::new(*offset)).to_le_bytes()),
|
Self::Jal(dest, offset) => jal(*dest, BitsI32::new(*offset)),
|
||||||
Self::Ja(sym) => {
|
Self::J(sym) => {
|
||||||
if let Some(addr) = sym_map.get(sym) {
|
if let Some(addr) = sym_map.get(*sym) {
|
||||||
let offset = *addr as i32 - pos as i32;
|
let offset = addr.val() as i32 - pos.val() as i32;
|
||||||
data.extend(j(BitsI32::new(offset)).to_le_bytes());
|
j(BitsI32::new(offset))
|
||||||
} else {
|
} else {
|
||||||
return Some(sym.to_string());
|
data.extend_from_slice(&[0; 4]);
|
||||||
|
return Some(*sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Jala(sym) => {
|
Self::Call(sym) => {
|
||||||
if let Some(addr) = sym_map.get(sym) {
|
if let Some(addr) = sym_map.get(*sym) {
|
||||||
let offset = *addr as i32 - pos as i32;
|
let offset = addr.val() as i32 - pos.val() as i32;
|
||||||
data.extend(jal(ra, BitsI32::new(offset)).to_le_bytes());
|
jal(ra, BitsI32::new(offset))
|
||||||
} else {
|
} else {
|
||||||
return Some(sym.to_string());
|
data.extend_from_slice(&[0; 4]);
|
||||||
|
return Some(*sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Ret => data.extend(ret().to_le_bytes()),
|
Self::Ret => ret(),
|
||||||
Self::Ecall => data.extend(ecall().to_le_bytes()),
|
Self::Ecall => ecall(),
|
||||||
}
|
Self::Li(reg, val) => addi(*reg, zero, BitsI32::new(*val)),
|
||||||
|
};
|
||||||
|
data.extend(last.to_le_bytes());
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ mod opcode;
|
|||||||
mod reg;
|
mod reg;
|
||||||
mod single;
|
mod single;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use super::{create_program, elf, SymMap};
|
||||||
|
|
||||||
use super::{elf, program::{create_program, Function}};
|
|
||||||
use crate::util::BitsI32;
|
use crate::util::BitsI32;
|
||||||
use base::*;
|
use base::*;
|
||||||
use funct::{op::*, width};
|
use funct::{op::*, width};
|
||||||
@@ -18,64 +16,33 @@ use single::*;
|
|||||||
|
|
||||||
pub fn gen() -> Vec<u8> {
|
pub fn gen() -> Vec<u8> {
|
||||||
use asm::AsmInstruction as I;
|
use asm::AsmInstruction as I;
|
||||||
// let mut program = Vec::new();
|
let mut table = SymMap::new();
|
||||||
// let msg = b"Hello world!\n";
|
let (msg, len) = table.push_ro_data(b"Hello world!\n");
|
||||||
// program.extend(msg);
|
let (msg2, len2) = table.push_ro_data(b"IT WORKS!!!!\n");
|
||||||
// program.resize(((program.len() - 1) / 4 + 1) * 4, 0);
|
let print_stuff = table.reserve();
|
||||||
// let start = program.len() as u64;
|
let start = table.push_fn(vec![
|
||||||
// let instructions = [
|
I::Call(*print_stuff),
|
||||||
// auipc(t0, BitsI32::new(0)),
|
I::Li(a0, 0),
|
||||||
// addi(t0, t0, BitsI32::new(-(start as i32))),
|
I::Li(a7, 93),
|
||||||
// addi(a0, zero, BitsI32::new(1)),
|
|
||||||
// mv(a1, t0),
|
|
||||||
// addi(a2, zero, BitsI32::new(msg.len() as i32)),
|
|
||||||
// addi(a7, zero, BitsI32::new(64)),
|
|
||||||
// addi(t0, zero, const { BitsI32::new(-10) }),
|
|
||||||
// ecall(),
|
|
||||||
// // exit
|
|
||||||
// addi(a0, zero, BitsI32::new(0)),
|
|
||||||
// addi(a7, zero, BitsI32::new(93)),
|
|
||||||
// ecall(),
|
|
||||||
// j(BitsI32::new(0)),
|
|
||||||
// ];
|
|
||||||
// for i in instructions {
|
|
||||||
// program.extend(i.to_le_bytes());
|
|
||||||
// }
|
|
||||||
let msg = b"Hello world!\n";
|
|
||||||
let msg2 = b"IT WORKS!!!!\n";
|
|
||||||
let ro_data = HashMap::from([
|
|
||||||
("msg".to_string(), msg.to_vec()),
|
|
||||||
("msg2".to_string(), msg2.to_vec()),
|
|
||||||
]);
|
|
||||||
let functions = vec![
|
|
||||||
Function {
|
|
||||||
label: "print_stuff".to_string(),
|
|
||||||
instructions: vec![
|
|
||||||
I::Addi(a0, zero, 1),
|
|
||||||
I::La(a1, "msg".to_string()),
|
|
||||||
I::Addi(a2, zero, msg.len() as i32),
|
|
||||||
I::Addi(a7, zero, 64),
|
|
||||||
I::Ecall,
|
|
||||||
I::Addi(a0, zero, 1),
|
|
||||||
I::La(a1, "msg2".to_string()),
|
|
||||||
I::Addi(a2, zero, msg2.len() as i32),
|
|
||||||
I::Addi(a7, zero, 64),
|
|
||||||
I::Ecall,
|
|
||||||
I::Ret,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
Function {
|
|
||||||
label: "_start".to_string(),
|
|
||||||
instructions: vec![
|
|
||||||
I::Jala("print_stuff".to_string()),
|
|
||||||
I::Ecall,
|
|
||||||
I::Addi(a0, zero, 0),
|
|
||||||
I::Addi(a7, zero, 93),
|
|
||||||
I::Ecall,
|
I::Ecall,
|
||||||
I::Jal(zero, 0),
|
I::Jal(zero, 0),
|
||||||
]
|
]);
|
||||||
},
|
table.write_fn(
|
||||||
];
|
print_stuff,
|
||||||
let (program, start) = create_program(ro_data, functions);
|
vec![
|
||||||
|
I::Li(a0, 1),
|
||||||
|
I::La(a1, msg),
|
||||||
|
I::Li(a2, len as i32),
|
||||||
|
I::Li(a7, 64),
|
||||||
|
I::Ecall,
|
||||||
|
I::Li(a0, 1),
|
||||||
|
I::La(a1, msg2),
|
||||||
|
I::Li(a2, len2 as i32),
|
||||||
|
I::Li(a7, 64),
|
||||||
|
I::Ecall,
|
||||||
|
I::Ret,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let (program, start) = create_program(table, start);
|
||||||
elf::create(program, start.expect("no start!"))
|
elf::create(program, start.expect("no start!"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(const_unbounded_shifts)]
|
|
||||||
#![feature(unbounded_shifts)]
|
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
mod compiler;
|
mod compiler;
|
||||||
|
|||||||
Reference in New Issue
Block a user