summaryrefslogtreecommitdiff
path: root/tools/proxyclient/m1n1/asm.py
diff options
context:
space:
mode:
authormagh <magh@maghmogh.com>2023-03-06 18:44:55 -0600
committermagh <magh@maghmogh.com>2023-03-06 18:44:55 -0600
commite80d9d8871b325a04b18f90a9ea4bb7fd148fb25 (patch)
tree79dbdb8506b7ff1e92549188d1b94cfc0b3503ae /tools/proxyclient/m1n1/asm.py
add m1n1HEADmaster
Diffstat (limited to 'tools/proxyclient/m1n1/asm.py')
-rw-r--r--tools/proxyclient/m1n1/asm.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/asm.py b/tools/proxyclient/m1n1/asm.py
new file mode 100644
index 0000000..ef1f3af
--- /dev/null
+++ b/tools/proxyclient/m1n1/asm.py
@@ -0,0 +1,133 @@
+# SPDX-License-Identifier: MIT
+import os, tempfile, shutil, subprocess
+
+__all__ = ["AsmException", "ARMAsm"]
+
+uname = os.uname()
+
+if uname.sysname == "Darwin":
+ DEFAULT_ARCH = "aarch64-linux-gnu-"
+ if uname.machine == "arm64":
+ TOOLCHAIN = "/opt/homebrew/opt/llvm/bin/"
+ else:
+ TOOLCHAIN = "/usr/local/opt/llvm/bin/"
+ USE_CLANG = "1"
+else:
+ if uname.machine == "aarch64":
+ DEFAULT_ARCH = ""
+ else:
+ DEFAULT_ARCH = "aarch64-linux-gnu-"
+ USE_CLANG = "0"
+ TOOLCHAIN = ""
+
+use_clang = os.environ.get("USE_CLANG", USE_CLANG).strip() == "1"
+toolchain = os.environ.get("TOOLCHAIN", TOOLCHAIN)
+
+if use_clang:
+ CC = toolchain + "clang --target=%ARCH"
+ LD = toolchain + "ld.lld"
+ OBJCOPY = toolchain + "llvm-objcopy"
+ OBJDUMP = toolchain + "llvm-objdump"
+ NM = toolchain + "llvm-nm"
+else:
+ CC = toolchain + "%ARCHgcc"
+ LD = toolchain + "%ARCHld"
+ OBJCOPY = toolchain + "%ARCHobjcopy"
+ OBJDUMP = toolchain + "%ARCHobjdump"
+ NM = toolchain + "%ARCHnm"
+
+class AsmException(Exception):
+ pass
+
+class BaseAsm(object):
+ def __init__(self, source, addr = 0):
+ self.source = source
+ self._tmp = tempfile.mkdtemp() + os.sep
+ self.addr = addr
+ self.compile(source)
+
+ def _call(self, program, args):
+ subprocess.check_call(program.replace("%ARCH", self.ARCH) + " " + args, shell=True)
+
+ def _get(self, program, args):
+ return subprocess.check_output(program.replace("%ARCH", self.ARCH) + " " + args, shell=True).decode("ascii")
+
+ def compile(self, source):
+ self.sfile = self._tmp + "b.S"
+ with open(self.sfile, "w") as fd:
+ fd.write(self.HEADER + "\n")
+ fd.write(source + "\n")
+ fd.write(self.FOOTER + "\n")
+
+ self.ofile = self._tmp + "b.o"
+ self.elffile = self._tmp + "b.elf"
+ self.bfile = self._tmp + "b.b"
+ self.nfile = self._tmp + "b.n"
+
+ self._call(CC, f"{self.CFLAGS} -c -o {self.ofile} {self.sfile}")
+ self._call(LD, f"{self.LDFLAGS} --Ttext={self.addr:#x} -o {self.elffile} {self.ofile}")
+ self._call(OBJCOPY, f"-j.text -O binary {self.elffile} {self.bfile}")
+ self._call(NM, f"{self.elffile} > {self.nfile}")
+
+ with open(self.bfile, "rb") as fd:
+ self.data = fd.read()
+
+ with open(self.nfile) as fd:
+ for line in fd:
+ line = line.replace("\n", "")
+ addr, type, name = line.split()
+ addr = int(addr, 16)
+ setattr(self, name, addr)
+ self.start = self._start
+ self.len = len(self.data)
+ self.end = self.start + self.len
+
+ def objdump(self):
+ self._call(OBJDUMP, f"-rd {self.elffile}")
+
+ def disassemble(self):
+ output = self._get(OBJDUMP, f"-zd {self.elffile}")
+
+ for line in output.split("\n"):
+ if not line or line.startswith("/"):
+ continue
+ sl = line.split()
+ if not sl or sl[0][-1] != ":":
+ continue
+ yield line
+
+ def __del__(self):
+ if self._tmp:
+ shutil.rmtree(self._tmp)
+ self._tmp = None
+
+class ARMAsm(BaseAsm):
+ ARCH = os.path.join(os.environ.get("ARCH", DEFAULT_ARCH))
+ CFLAGS = "-pipe -Wall -march=armv8.4-a"
+ LDFLAGS = "-maarch64elf"
+ HEADER = """
+ .text
+ .globl _start
+_start:
+ """
+ FOOTER = """
+ .pool
+ """
+
+if __name__ == "__main__":
+ import sys
+ code = """
+ ldr x0, =0xDEADBEEF
+ b test
+ mrs x0, spsel
+ svc 1
+ %s
+test:
+ b test
+ ret
+""" % (" ".join(sys.argv[1:]))
+ c = ARMAsm(code, 0x1238)
+ c.objdump()
+ assert c.start == 0x1238
+ if not sys.argv[1:]:
+ assert c.test == 0x1248