add, use coproc_manager

This commit is contained in:
Jeff Epler 2022-10-23 18:39:13 -05:00
parent 5e5d1800b6
commit dc16588575
No known key found for this signature in database
GPG key ID: D5BF15AB975AB4DE
5 changed files with 74 additions and 40 deletions

17
py/coproc_manager.py Normal file
View file

@ -0,0 +1,17 @@
import minielf
class Program:
def __init__(self, filename):
self.elf = minielf.ELFFile(open(filename, "rb"))
code_header = self.elf.get_header_by_type(minielf.PT_LOAD)
self.code = bytes(self.elf.pread(code_header.p_offset, code_header.p_filesz))
self.symtab = self.elf.get_section_by_name('.symtab')
def get_code(self):
return
def get_symbol(self, name):
r = self.symtab.get_first_symbol_by_name(name)
if r is None:
raise ValueError(f"{repr(name)} not found")
return r

View file

@ -1,26 +1,28 @@
import time import time
import struct import struct
from coproc import * from coproc import *
from minidump import e, h, en from coproc_manager import Program
def storele32(cm, off, x):
print(off, ":=", x) program = Program("/a.out-stripped")
cm[off:off+4] = struct.pack("<l", x) shared_mem = program.get_symbol('shared_mem').entry.st_value
def storele16(cm, off, x): print(f"{shared_mem=}")
print(off, ":=", x)
cm[off:off+2] = struct.pack("<h", x)
binary = e._readat(h.p_offset, h.p_filesz)
cm = CoprocMemory(0x50000000, 8176) cm = CoprocMemory(0x50000000, 8176)
off = en.st_value c = Coproc(program.code)
print(f"value at {off}, adjusted offset is {off}") print(f"{shared_mem=}")
c = Coproc(binary)
try: try:
run(c) run(c)
while True: while True:
cm[off] = 10 cm[shared_mem] = 10
time.sleep(2) time.sleep(2)
cm[off] = 20 cm[shared_mem] = 20
time.sleep(2) time.sleep(2)
finally: finally:
print("about to halt")
time.sleep(.2)
halt(c) halt(c)
print("returned from halt")
time.sleep(.2)

View file

@ -6,12 +6,13 @@ a_out = open("a.out-stripped", "rb")
e = ELFFile(a_out) e = ELFFile(a_out)
s = e.get_section(1) s = e.get_section(1)
s = e.get_section_by_name('.symtab') s = e.get_section_by_name('.symtab')
sy = s.get_symbol_by_name('shared_mem')[0] print(s)
sy = s.get_first_symbol_by_name('shared_mem')
en = sy.entry en = sy.entry
for h in e.iter_headers(): for h in e.iter_headers():
if h.p_type == PT_LOAD: if h.p_type == PT_LOAD:
print(f"@{h.p_vaddr:04x}: Load {h.p_filesz} bytes starting at {h.p_offset}") print(f"@{h.p_vaddr:04x}: Load {h.p_filesz} bytes starting at {h.p_offset}")
content = e._readat(h.p_offset, 16) content = e.pread(h.p_offset, 16)
print(" ".join(f"{b:02x}" for b in content)) print(" ".join(f"{b:02x}" for b in content))
print(f"shared_mem @ 0x{en.st_value:04x} 0x{en.st_size:04x} bytes") print(f"shared_mem @ 0x{en.st_value:04x} 0x{en.st_size:04x} bytes")

View file

@ -29,9 +29,9 @@ class Section:
self._header = sh self._header = sh
def readat(self, offset, sz): def readat(self, offset, sz):
return self._elffile._readat(offset + self._header.sh_offset, sz) return self._elffile.pread(offset + self._header.sh_offset, sz)
def constructat(self, offset, cls): def constructat(self, offset, cls):
return self._elffile._constructat(offset + self._header.sh_offset, cls) return self._elffile.construct_at(offset + self._header.sh_offset, cls)
class StringTable(Section): class StringTable(Section):
def symbolat(self, offset): def symbolat(self, offset):
@ -42,6 +42,15 @@ class StringTable(Section):
result += c result += c
return result return result
def symbolat_matches(self, offset, name):
stream = self._elffile.stream
stream.seek(self._header.sh_offset + offset)
name1 = stream.read(len(name))
if name1 != name: return False
nul = stream.read(1)
if nul != b'\0': return False
return True
_SymbolTableEntry = namedtuple('_SymbolTableEntry', _SymbolTableEntry = namedtuple('_SymbolTableEntry',
['st_name', 'st_value', 'st_size', 'set_info', 'st_other', 'st_shndx']) ['st_name', 'st_value', 'st_size', 'set_info', 'st_other', 'st_shndx'])
@ -54,17 +63,22 @@ class Symbol:
self.entry = entry self.entry = entry
class SymbolTable(Section): class SymbolTable(Section):
def __init__(self, ef, sh):
super().__init__(ef, sh)
self.strtab = None
def iter_symbols(self): def iter_symbols(self):
for i in range(0, self._header.sh_size, SymbolTableEntry.calcsize()): for i in range(0, self._header.sh_size, SymbolTableEntry.calcsize()):
yield self.constructat(i, SymbolTableEntry) yield self.constructat(i, SymbolTableEntry)
def get_symbol_by_name(self, name): def get_first_symbol_by_name(self, name):
if not isinstance(name, bytes): name = name.encode() if not isinstance(name, bytes): name = name.encode()
strs = self._elffile.get_section_by_name('.strtab') if self.strtab is None:
self.strtab = self._elffile.get_section_by_name('.strtab')
strtab = self.strtab
for sy in self.iter_symbols(): for sy in self.iter_symbols():
name2 = strs.symbolat(sy.st_name) if strtab.symbolat_matches(sy.st_name, name):
if name == name2: return Symbol(name, sy)
return [Symbol(name, sy)]
section_constructors = { section_constructors = {
@ -84,13 +98,13 @@ class ELFFile:
def __init__(self, stream): def __init__(self, stream):
self.stream = stream self.stream = stream
self._buffer = () self._buffer = ()
if self._readat(0, 4) != b'\177ELF': if self.pread(0, 4) != b'\177ELF':
raise ValueError("Not an ELF file") raise ValueError("Not an ELF file")
if self._readat(4, 3) != b'\1\1\1': if self.pread(4, 3) != b'\1\1\1':
raise ValueError("Incompatible ELF file") raise ValueError("Incompatible ELF file")
self._header = self._constructat(0, ElfHeader32) self._header = self.construct_at(0, ElfHeader32)
def _readat(self, offset, sz): def pread(self, offset, sz):
if len(self._buffer) < sz: if len(self._buffer) < sz:
self._buffer = bytearray(sz) self._buffer = bytearray(sz)
self._view = memoryview(self._buffer) self._view = memoryview(self._buffer)
@ -99,21 +113,16 @@ class ELFFile:
self.stream.readinto(mv) self.stream.readinto(mv)
return mv return mv
def _decodeat(self, offset, fmt): def construct_at(self, offset, cls):
sz = struct.calcsize(fmt)
mb = self._readat(offset, sz)
return struct.unpack(fmt, mv)
def _constructat(self, offset, cls):
sz = cls.calcsize() sz = cls.calcsize()
mb = self._readat(offset, sz) mb = self.pread(offset, sz)
return cls.frombuffer(mb) return cls.frombuffer(mb)
def get_section(self, index): def get_section(self, index):
if not (0 <= index < self._header.e_shnum): if not (0 <= index < self._header.e_shnum):
raise IndexError("Invalid section number") raise IndexError("Invalid section number")
offset = self._header.e_shoff + index * self._header.e_shentsize offset = self._header.e_shoff + index * self._header.e_shentsize
sh = self._constructat(offset, SectionHeader32) sh = self.construct_at(offset, SectionHeader32)
constructor = section_constructors.get(sh.sh_type, Section) constructor = section_constructors.get(sh.sh_type, Section)
return constructor(self, sh) return constructor(self, sh)
@ -126,16 +135,20 @@ class ELFFile:
idx = self.get_section(self._header.e_shstrndx) idx = self.get_section(self._header.e_shstrndx)
for sec in self.iter_sections(): for sec in self.iter_sections():
off = sec._header.sh_name off = sec._header.sh_name
name2 = idx.symbolat(off) if idx.symbolat_matches(sec._header.sh_name, name):
if name == name2:
return sec return sec
def get_header(self, index): def get_header(self, index):
if not (0 <= index < self._header.e_phnum): if not (0 <= index < self._header.e_phnum):
raise IndexError("Invalid header number") raise IndexError("Invalid header number")
offset = self._header.e_phoff + index * self._header.e_phentsize offset = self._header.e_phoff + index * self._header.e_phentsize
return self._constructat(offset, HeaderTableEntry) return self.construct_at(offset, HeaderTableEntry)
def iter_headers(self): def iter_headers(self):
for i in range(self._header.e_phnum): for i in range(self._header.e_phnum):
yield self.get_header(i) yield self.get_header(i)
def get_header_by_type(self, p_type):
for h in self.iter_headers():
if h.p_type == p_type:
return h

7
ulp.c
View file

@ -15,17 +15,18 @@ EXPORT uint16_t shared_mem_len = 1024;
#undef ULP_RISCV_CYCLES_PER_MS #undef ULP_RISCV_CYCLES_PER_MS
#define ULP_RISCV_CYCLES_PER_MS (int)(1000*ULP_RISCV_CYCLES_PER_US) #define ULP_RISCV_CYCLES_PER_MS (int)(1000*ULP_RISCV_CYCLES_PER_US)
#define GPIO (GPIO_NUM_3)
int main (void) { int main (void) {
shared_mem[0] = 10; shared_mem[0] = 10;
shared_mem_len = 1024; shared_mem_len = 1024;
bool gpio_level = true; bool gpio_level = true;
ulp_riscv_gpio_init(GPIO_NUM_21); ulp_riscv_gpio_init(GPIO);
ulp_riscv_gpio_output_enable(GPIO_NUM_21); ulp_riscv_gpio_output_enable(GPIO);
while(1) { while(1) {
ulp_riscv_gpio_output_level(GPIO_NUM_21, gpio_level); ulp_riscv_gpio_output_level(GPIO, gpio_level);
ulp_riscv_delay_cycles(shared_mem[0] * 10 * ULP_RISCV_CYCLES_PER_MS); ulp_riscv_delay_cycles(shared_mem[0] * 10 * ULP_RISCV_CYCLES_PER_MS);
gpio_level = !gpio_level; gpio_level = !gpio_level;
} }