diff options
| author | magh <magh@maghmogh.com> | 2023-03-06 18:44:55 -0600 |
|---|---|---|
| committer | magh <magh@maghmogh.com> | 2023-03-06 18:44:55 -0600 |
| commit | e80d9d8871b325a04b18f90a9ea4bb7fd148fb25 (patch) | |
| tree | 79dbdb8506b7ff1e92549188d1b94cfc0b3503ae /tools/proxyclient/m1n1/asm.py | |
Diffstat (limited to 'tools/proxyclient/m1n1/asm.py')
| -rw-r--r-- | tools/proxyclient/m1n1/asm.py | 133 |
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 |
