Skip to content

Commit 097b4aa

Browse files
authored
Merge pull request #1551 from panda-re/sw_support
Updating and adding architecture support in pypanda.
2 parents 1fcdf85 + 706c088 commit 097b4aa

File tree

4 files changed

+116
-47
lines changed

4 files changed

+116
-47
lines changed

hw/avatar/configurable_machine.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,9 @@ static void set_entry_point(QDict *conf, THISCPU *cpuu)
438438
cpuu->env.active_tc.PC = entry;
439439

440440
#elif defined(TARGET_PPC)
441+
cpuu->env.nip = entry;
441442
//Not implemented yet
442-
fprintf(stderr, "Not yet implemented- can't start execution at 0x%x\n", entry);
443+
//fprintf(stderr, "Not yet implemented- can't start execution at 0x%x\n", entry);
443444
#endif
444445

445446
}

panda/python/core/pandare/arch.py

Lines changed: 97 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ def __init__(self, panda):
369369
regnames = ["X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7",
370370
"XR", "X9", "X10", "X11", "X12", "X13", "X14",
371371
"X15", "IP0", "IP1", "PR", "X19", "X20", "X21",
372-
"X22", "X23", "X24", "X25", "X26", "X27", "X27",
372+
"X22", "X23", "X24", "X25", "X26", "X27",
373373
"X28", "FP", "LR", "SP"]
374374

375375
self.reg_sp = regnames.index("SP")
@@ -601,6 +601,7 @@ def set_retval(self, cpu, val, convention='default', failure=False):
601601

602602
return super().set_retval(cpu, val, convention)
603603

604+
604605
class Mips64Arch(MipsArch):
605606
'''
606607
Register names and accessors for MIPS64. Inherits from MipsArch for everything
@@ -629,67 +630,71 @@ def __init__(self, panda):
629630
# note names must be stored uppercase for get/set reg to work case-insensitively
630631
self.registers = {regnames[idx].upper(): idx for idx in range(len(regnames)) }
631632

632-
class X86Arch(PandaArch):
633+
class PowerPCArch(PandaArch):
633634
'''
634-
Register names and accessors for x86
635+
Register names and accessors for ppc
635636
'''
636-
637-
def __init__(self, panda):
637+
def __init__(self, panda):
638638
super().__init__(panda)
639-
regnames = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI']
640-
# XXX Note order is A C D B, because that's how qemu does it . See target/i386/cpu.h
641-
642-
# Note we don't set self.call_conventions because stack-based arg get/set is
643-
# not yet supported
644-
self.reg_retval = {"default": "EAX",
645-
"syscall": "EAX",
646-
"linux_kernel": "EAX"}
647-
648-
self.call_conventions = {"cdecl": [f"stack_{x}" for x in range(20)], # 20: arbitrary but big
649-
"syscall": ["EAX", "EBX", "ECX", "EDX", "ESI", "EDI", "EBP"],
650-
"linux_kernel": ["EAX", "EDX", "ECX", "stack_3", "stack_4", "stack_5", "stack_6"]}
651-
self.call_conventions['default'] = self.call_conventions['cdecl']
652-
653-
self.reg_sp = regnames.index('ESP')
654-
self.registers = {regnames[idx]: idx for idx in range(len(regnames)) }
655-
639+
regnames = ["r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
640+
"r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22",
641+
"r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"]
642+
self.reg_sp = regnames.index('sp')
643+
self.registers = {regnames[idx].upper(): idx for idx in range(len(regnames)) }
644+
self.registers_crf = ["CR0", "CR1", "CR2", "CR3", "CR4", "CR5", "CR6", "CR7"]
656645

657646
def get_pc(self, cpu):
658647
'''
659-
Overloaded function to return the x86 current program counter
648+
Overloaded function to return the ppc current program counter
660649
'''
661-
return cpu.env_ptr.eip
650+
return cpu.env_ptr.nip
662651

663652
def set_pc(self, cpu, val):
664653
'''
665-
Overloaded function to set the x86 program counter
654+
Overloaded function to set the ppc program counter
666655
'''
667-
cpu.env_ptr.eip = val
656+
cpu.env_ptr.nip = val
668657

669658
def _get_reg_val(self, cpu, reg):
670659
'''
671-
Return an x86 register
660+
Return a ppc register
672661
'''
673-
return cpu.env_ptr.regs[reg]
662+
return cpu.env_ptr.gpr[reg]
674663

675664
def _set_reg_val(self, cpu, reg, val):
676665
'''
677-
Set an x86 register
666+
Set an x86_64 register
678667
'''
679-
cpu.env_ptr.regs[reg] = val
668+
cpu.env_ptr.gpr[reg] = val
669+
670+
def get_reg(self, cpu, reg):
671+
672+
reg = reg.upper()
673+
env = cpu.env_ptr
674+
if reg == "LR":
675+
return env.lr
676+
elif reg == "CTR":
677+
return env.ctr
678+
elif reg in self.registers_crf:
679+
return env.crf[self.registers_crf.index(reg)]
680+
else:
681+
return super().get_reg(cpu, reg)
682+
683+
684+
def set_reg(self, cpu, reg, val):
685+
reg = reg.upper()
686+
env = cpu.env_ptr
687+
688+
if reg == "LR":
689+
env.lr = val
690+
elif reg == "CTR":
691+
env.ctr = val
692+
elif reg in self.registers_crf:
693+
env.crf[self.registers_crf.index(reg)] = val
694+
else:
695+
super().set_reg(cpu, reg, val)
680696

681-
def get_return_value(self, cpu):
682-
'''
683-
.. Deprecated:: use get_retval
684-
'''
685-
return self.get_retval(cpu)
686697

687-
def get_return_address(self,cpu):
688-
'''
689-
looks up where ret will go
690-
'''
691-
esp = self.get_reg(cpu,"ESP")
692-
return self.panda.virtual_memory_read(cpu,esp,4,fmt='int')
693698

694699
class X86_64Arch(PandaArch):
695700
'''
@@ -722,6 +727,7 @@ def __init__(self, panda):
722727
self.reg_names_short = ['AX', 'CX', 'DX', 'BX', 'SP', 'BP', 'SI', 'DI']
723728
self.reg_names_byte = ['AL', 'CL', 'DL', 'BL', 'AH', 'CH', 'DH', 'BH']
724729
self.seg_names = ['ES', 'CS', 'SS', 'DS', 'FS', 'GS']
730+
self.reg_names_mmr = ['LDT', 'TR', 'GDT', 'IDT']
725731

726732
def _get_segment_register(self, env, seg_name):
727733
seg_idx = self.seg_names.index(seg_name)
@@ -765,6 +771,20 @@ def set_pc(self, cpu, val):
765771
'''
766772
cpu.env_ptr.eip = val
767773

774+
def _get_mmr_val(self, cpu, reg):
775+
reg = reg.lower()
776+
sc = getattr(cpu.env_ptr, reg)
777+
return (sc.selector, sc.base, sc.limit, sc.flags)
778+
779+
def _set_mmr_val(self, cpu, reg, val):
780+
reg = reg.lower()
781+
selector, base, limit, flags = val
782+
sc = getattr(cpu.env_ptr, reg)
783+
sc.selector = selector
784+
sc.base = base
785+
sc.limit = limit
786+
sc.flags = flags
787+
768788
def _get_reg_val(self, cpu, reg):
769789
'''
770790
Return an x86_64 register
@@ -802,8 +822,12 @@ def get_reg(self, cpu, reg):
802822

803823
reg = reg.upper()
804824
env = cpu.env_ptr
825+
if reg in self.reg_names_mmr:
826+
return self._get_mmr_val(cpu, reg)
805827
if reg in self.seg_names:
806828
return self._get_segment_register(env, reg)
829+
elif reg in ['EFLAGS', 'RFLAGS']:
830+
return env.eflags
807831
elif reg in ['RIP', 'PC', 'EIP']:
808832
pc = self.get_pc(cpu) # changes reg to 'IP' and re-calls this
809833
if reg == 'EIP':
@@ -856,13 +880,17 @@ def set_reg(self, cpu, reg, val):
856880
reg = reg.upper()
857881
env = cpu.env_ptr
858882

859-
if reg in ['ES', 'CS', 'SS', 'DS', 'FS', 'GS']:
883+
if reg in self.reg_names_mmr:
884+
return self._set_mmr_val(cpu, reg, val)
885+
elif reg in self.seg_names:
860886
self._set_segment_register(env, reg, val)
887+
elif reg in ['EFLAGS', 'RFLAGS']:
888+
env.eflags = val
861889
elif reg in ['RIP', 'PC']:
862890
return self.set_pc(cpu, val) # changes reg to 'IP' and re-calls this
863891
elif reg.startswith('XMM'):
864-
#env.xmm_regs[int(reg[3:])] = val
865-
raise NotImplementedError("XMM registers unsupported")
892+
env.xmm_regs[int(reg[3:])] = val
893+
#raise NotImplementedError("XMM registers unsupported")
866894
elif reg.startswith('MM'):
867895
raise NotImplementedError("MM registers unsupported")
868896
elif reg.startswith('YMM'):
@@ -890,3 +918,28 @@ def set_reg(self, cpu, reg, val):
890918
self._set_general_purpose_register(env, reg, val, mask)
891919
else:
892920
super().set_reg(cpu, reg, val)
921+
922+
923+
class X86Arch(X86_64Arch):
924+
'''
925+
Register names and accessors for x86
926+
'''
927+
928+
def __init__(self, panda):
929+
super().__init__(panda)
930+
regnames = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI']
931+
# XXX Note order is A C D B, because that's how qemu does it . See target/i386/cpu.h
932+
933+
# Note we don't set self.call_conventions because stack-based arg get/set is
934+
# not yet supported
935+
self.reg_retval = {"default": "EAX",
936+
"syscall": "EAX",
937+
"linux_kernel": "EAX"}
938+
939+
self.call_conventions = {"cdecl": [f"stack_{x}" for x in range(20)], # 20: arbitrary but big
940+
"syscall": ["EAX", "EBX", "ECX", "EDX", "ESI", "EDI", "EBP"],
941+
"linux_kernel": ["EAX", "EDX", "ECX", "stack_3", "stack_4", "stack_5", "stack_6"]}
942+
self.call_conventions['default'] = self.call_conventions['cdecl']
943+
944+
self.reg_sp = regnames.index('ESP')
945+
self.registers = {regnames[idx]: idx for idx in range(len(regnames)) }

panda/python/core/pandare/panda.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from .asyncthread import AsyncThread
3838
from .qcows_internal import Qcows
3939
from .qemu_logging import QEMU_Log_Manager
40-
from .arch import ArmArch, Aarch64Arch, MipsArch, Mips64Arch, X86Arch, X86_64Arch
40+
from .arch import ArmArch, Aarch64Arch, MipsArch, Mips64Arch, X86Arch, X86_64Arch, PowerPCArch
4141
from .cosi import Cosi
4242
from dataclasses import dataclass
4343

@@ -150,6 +150,8 @@ def __init__(self, arch="i386", mem="128M",
150150
self.arch = MipsArch(self)
151151
elif self.arch_name in ["mips64", "mips64el"]:
152152
self.arch = Mips64Arch(self)
153+
elif self.arch_name in ["ppc"]:
154+
self.arch = PowerPCArch(self)
153155
else:
154156
raise ValueError(f"Unsupported architecture {self.arch_name}")
155157
self.bits, self.endianness, self.register_size = self.arch._determine_bits()

target/ppc/translate_init.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9814,6 +9814,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
98149814
error_propagate(errp, local_err);
98159815
return;
98169816
}
9817+
cpu_reset(cs);
98179818

98189819
#if !defined(CONFIG_USER_ONLY)
98199820
cpu->cpu_dt_id = (cs->cpu_index / smp_threads) * max_smt
@@ -10247,7 +10248,19 @@ const char *ppc_cpu_lookup_alias(const char *alias)
1024710248

1024810249
PowerPCCPU *cpu_ppc_init(const char *cpu_model)
1024910250
{
10250-
return POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model));
10251+
ObjectClass *cpu_oc;
10252+
Object *cpuobj;
10253+
10254+
cpu_oc = cpu_class_by_name(TYPE_POWERPC_CPU, cpu_model);
10255+
if (cpu_oc == NULL) {
10256+
error_report("Unable to find CPU definition: %s", cpu_model);
10257+
exit(1);
10258+
}
10259+
cpuobj = object_new(object_class_get_name(cpu_oc));
10260+
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
10261+
return POWERPC_CPU(cpuobj);
10262+
10263+
//return POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model));
1025110264
}
1025210265

1025310266
/* Sort by PVR, ordering special case "host" last. */

0 commit comments

Comments
 (0)