Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

overhauls target/value abstraction and introduces roles (4/n) #1275

Merged
merged 1 commit into from
Feb 22, 2021

Conversation

ivg
Copy link
Member

@ivg ivg commented Feb 22, 2021

This PR is the continuation of the #1225, #1226, and #1227 series of
changes that were focused on substituting the old and inextensible
Arch.t abstraction with the new Theory.Target.t representation.

This episode is instigated by the upcoming implementation of the
RISCV target. Since RISCV is the out target that is not supported with
Arch.t it became a good test of the new Theory.Target.t abstraction.

As the RISCV worked showed, we still have lots of code that depends on
Arch.t, most importantly Primus, which was fully dependent on
Arch.t. The main issue was that Theory.Target.t doesn't provide any
means to encode register classes, which prevented us from using it
everywhere in Primus, e.g., we need to know which register is the
stack pointer in order to setup the stack.

To implement this, we introduce a new abstraction called role. A
role could be generally applied to any entity but so far we are only
talking about the roles of registers in various targets. The target
definiton now acccepts the regs paramater that takes the register
file specification with each register assigned one or more roles,
e.g., here is the register file specification for 8086,

Theory.Role.Register.[
 [general; integer], main @< index @< segment;
 [stack_pointer], untyped [reg r16 "SP"];
 [frame_pointer], untyped [reg r16 "BP"];
 [Role.index], untyped index;
 [Role.segment], untyped segment;
 [status], untyped flags;
 [integer], untyped [
   reg bool "CF";
   reg bool "PF";
   reg bool "AF";
   reg bool "ZF";
   reg bool "SF";
   reg bool "OF";
]

I.e., we assign a set of roles to a set of registers. We also now have
two new functions Theory.Target.regs and Theory.Target.reg that
enable querying the register file of the target for register that
fulfill one or more roles. Whilst we publish a limited number of
well-known (blessed) roles in the Theory.Role.Register module, more
roles could be added as user need it. For example, in the code snippet
above we have two non-standard roles that are specific to the x86
architectures, Role.index and Role.segment.

With roles we can drop the dependency on Target in most of the places
where it makes sense (I still left it in x86 and other target-specific
plugins, which obviously are independent on the newly added
architectures).

This PR is the continuation of the BinaryAnalysisPlatform#1225, BinaryAnalysisPlatform#1226, and BinaryAnalysisPlatform#1227 series of
changes that were focused on substituting the old and inextensible
`Arch.t` abstraction with the new `Theory.Target.t` representation.

This episode is instigated by the upcoming implementation of the
RISCV target. Since RISCV is the out target that is not supported with
Arch.t it became a good test of the new Theory.Target.t abstraction.

As the RISCV worked showed, we still have lots of code that depends on
Arch.t, most importantly Primus, which was fully dependent on
Arch.t. The main issue was that Theory.Target.t doesn't provide any
means to encode register classes, which prevented us from using it
everywhere in Primus, e.g., we need to know which register is the
stack pointer in order to setup the stack.

To implement this, we introduce a new abstraction called _role_. A
_role_ could be generally applied to any entity but so far we are only
talking about the roles of registers in various targets. The target
definiton now acccepts the `regs` paramater that takes the register
file specification with each register assigned one or more roles,
e.g., here is the register file specification for 8086,

```ocaml
Theory.Role.Register.[
 [general; integer], main @< index @< segment;
 [stack_pointer], untyped [reg r16 "SP"];
 [frame_pointer], untyped [reg r16 "BP"];
 [Role.index], untyped index;
 [Role.segment], untyped segment;
 [status], untyped flags;
 [integer], untyped [
   reg bool "CF";
   reg bool "PF";
   reg bool "AF";
   reg bool "ZF";
   reg bool "SF";
   reg bool "OF";
]
```

I.e., we assign a set of roles to a set of registers. We also now have
two new functions `Theory.Target.regs` and `Theory.Target.reg` that
enable querying the register file of the target for register that
fulfill one or more roles. Whilst we publish a limited number of
well-known (blessed) roles in the `Theory.Role.Register` module, more
roles could be added as user need it. For example, in the code snippet
above we have two non-standard roles that are specific to the x86
architectures, `Role.index` and `Role.segment`.

With roles we can drop the dependency on Target in most of the places
where it makes sense (I still left it in x86 and other target-specific
plugins, which obviously are independent on the newly added
architectures).
@ivg ivg merged commit 52effe7 into BinaryAnalysisPlatform:master Feb 22, 2021
@ivg ivg deleted the overhauls-targets-part-4 branch December 1, 2021 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant