Skip to content

Commit cf1f961

Browse files
authored
Handle multiple flag registers (#25)
* Handle multiple flag registers * Explicit check for None return from SBFrame.register
1 parent fc7b50a commit cf1f961

File tree

6 files changed

+47
-34
lines changed

6 files changed

+47
-34
lines changed

arch/aarch64.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""aarch64 architecture definition."""
22

3-
from arch.base_arch import BaseArch
3+
from arch.base_arch import BaseArch, FlagRegister
44

55

66
class Aarch64(BaseArch):
@@ -50,10 +50,8 @@ class Aarch64(BaseArch):
5050

5151
gpr_key = "general"
5252

53-
flag_register = "cpsr"
54-
5553
# Bitmasks used to extract flag bits from cpsr register value
56-
flag_register_bit_masks = {
54+
_cpsr_register_bit_masks = {
5755
"n": 0x80000000,
5856
"z": 0x40000000,
5957
"c": 0x20000000,
@@ -69,3 +67,7 @@ class Aarch64(BaseArch):
6967
"f": 0x40,
7068
"m": 0xF,
7169
}
70+
71+
flag_registers = [
72+
FlagRegister("cpsr", _cpsr_register_bit_masks)
73+
]

arch/arm.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""arm architecture definition."""
22

3-
from arch.base_arch import BaseArch
3+
from arch.base_arch import BaseArch, FlagRegister
44

55

66
class Arm(BaseArch):
@@ -31,10 +31,8 @@ class Arm(BaseArch):
3131

3232
gpr_key = "general"
3333

34-
flag_register = "cpsr"
35-
3634
# Bitmasks used to extract flag bits from cpsr register value
37-
flag_register_bit_masks = {
35+
_cpsr_register_bit_masks = {
3836
"n": 0x80000000,
3937
"z": 0x40000000,
4038
"c": 0x20000000,
@@ -48,3 +46,7 @@ class Arm(BaseArch):
4846
"f": 0x40,
4947
"t": 0x20,
5048
}
49+
50+
flag_registers = [
51+
FlagRegister("cpsr", _cpsr_register_bit_masks)
52+
]

arch/base_arch.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
"""Base arch abstract class definition."""
22

33
from abc import ABC, abstractmethod
4+
from dataclasses import dataclass
45
from typing import Dict, List
56

67

8+
@dataclass
9+
class FlagRegister:
10+
"""FlagRegister dataclass to store register name / bitmask associations"""
11+
name: str
12+
bit_masks: Dict[str, int]
13+
14+
715
class BaseArch(ABC):
816
"""BaseArch abstract class definition."""
917

@@ -24,10 +32,5 @@ def gpr_key(self) -> str:
2432

2533
@property
2634
@abstractmethod
27-
def flag_register(self) -> str:
28-
"""Flag register property"""
29-
30-
@property
31-
@abstractmethod
32-
def flag_register_bit_masks(self) -> Dict[str, int]:
33-
"""Flag register bit mask property"""
35+
def flag_registers(self) -> List[FlagRegister]:
36+
"""List of flag registers with associated bit masks"""

arch/i386.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""i386 architecture definition."""
2-
from arch.base_arch import BaseArch
2+
from arch.base_arch import BaseArch, FlagRegister
33

44

55
class I386(BaseArch):
@@ -29,10 +29,8 @@ class I386(BaseArch):
2929

3030
gpr_key = "general purpose"
3131

32-
flag_register = "eflags"
33-
3432
# Bitmasks used to extract flag bits from eflags register value
35-
flag_register_bit_masks = {
33+
_eflags_register_bit_masks = {
3634
"zero": 0x40,
3735
"carry": 0x1,
3836
"parity": 0x4,
@@ -46,3 +44,7 @@ class I386(BaseArch):
4644
"virtual8086": 0x20000,
4745
"identification": 0x200000,
4846
}
47+
48+
flag_registers = [
49+
FlagRegister("eflags", _eflags_register_bit_masks)
50+
]

arch/x86_64.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""x86_64 architecture definition."""
2-
from arch.base_arch import BaseArch
2+
from arch.base_arch import BaseArch, FlagRegister
33

44

55
class X86_64(BaseArch):
@@ -31,10 +31,8 @@ class X86_64(BaseArch):
3131

3232
gpr_key = "general purpose"
3333

34-
flag_register = "rflags"
35-
36-
# Bitmasks used to extract flag bits from rflags register value
37-
flag_register_bit_masks = {
34+
# Bitmasks used to extract flag bits from eflags register value
35+
_eflag_register_bit_masks = {
3836
"zero": 0x40,
3937
"carry": 0x1,
4038
"parity": 0x4,
@@ -48,3 +46,10 @@ class X86_64(BaseArch):
4846
"virtualx86": 0x20000,
4947
"identification": 0x200000,
5048
}
49+
50+
# Whether LLDB exposes eflags or rflags varies depending on the platform
51+
# rflags and eflags bit masks are identical for the lower 32-bits
52+
flag_registers = [
53+
FlagRegister("rflags", _eflag_register_bit_masks),
54+
FlagRegister("eflags", _eflag_register_bit_masks)
55+
]

common/context_handler.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
)
1616

1717
from arch import get_arch
18-
from arch.base_arch import BaseArch
18+
from arch.base_arch import BaseArch, FlagRegister
1919
from common.constants import GLYPHS, TERM_COLOURS
2020
from common.util import (
2121
attempt_to_read_string_from_memory,
@@ -155,25 +155,22 @@ def print_register(self, register: SBValue) -> None:
155155

156156
print(line)
157157

158-
def print_flags_register(self, flag_register: SBValue) -> None:
158+
def print_flags_register(self, flag_register: FlagRegister) -> None:
159159
"""Format and print the contents of the flag register."""
160+
flag_value = self.frame.register[flag_register.name].GetValueAsUnsigned()
160161

161-
if (
162-
self.old_registers.get(self.arch().flag_register)
163-
== flag_register.GetValueAsUnsigned()
164-
):
162+
if self.old_registers.get(flag_register.name) == flag_value:
165163
# No change
166164
highlight = TERM_COLOURS.BLUE
167165
else:
168166
# Change and highlight
169167
highlight = TERM_COLOURS.RED
170168

171-
flag_value = flag_register.GetValueAsUnsigned()
172-
line = f"{highlight.value}{flag_register.GetName().ljust(7)}{TERM_COLOURS.ENDC.value}: ["
169+
line = f"{highlight.value}{flag_register.name.ljust(7)}{TERM_COLOURS.ENDC.value}: ["
173170
line += " ".join(
174171
[
175172
name.upper() if flag_value & bitmask else name
176-
for name, bitmask in self.arch().flag_register_bit_masks.items()
173+
for name, bitmask in flag_register.bit_masks.items()
177174
]
178175
)
179176
line += "]"
@@ -204,7 +201,9 @@ def display_registers(self) -> None:
204201
for reg in get_registers(self.frame, self.arch().gpr_key):
205202
if reg.GetName() in self.arch().gpr_registers:
206203
self.print_register(reg)
207-
self.print_flags_register(self.frame.register[self.arch.flag_register])
204+
for flag_register in self.arch.flag_registers:
205+
if self.frame.register[flag_register.name] is not None:
206+
self.print_flags_register(flag_register)
208207

209208
def display_stack(self) -> None:
210209
"""Print information about the contents of the top of the stack"""

0 commit comments

Comments
 (0)