Skip to content

Commit 640ae8d

Browse files
Implement aarch64 immediate range checking: Attempting to encode an overly big immediate will result in a panic at runtime, rather than the wrong immediate being encoded.
1 parent c225c6a commit 640ae8d

File tree

10 files changed

+752
-445
lines changed

10 files changed

+752
-445
lines changed

plugin/src/arch/aarch64/aarch64data.rs

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,26 +90,79 @@ pub enum Command {
9090
RNext, // encode that this register should be the previous register, plus one
9191

9292
// unsigned immediate encodings
93-
Ubits(u8, u8), // encodes an unsigned immediate starting at bit .0, .1 bits long
94-
Uscaled(u8, u8, u8), // encodes an unsigned immediate, starting at bit .0, .1 bits long, shifted .2 bits to the right before encoding
95-
Ulist(u8, &'static [u16]), // encodes an immediate that can only be a limited amount of options
96-
Urange(u8, u8, u8), // (loc, min, max) asserts the immediate is below or equal to max, encodes the value of (imm-min)
97-
Usub(u8, u8, u8), // encodes at .0, .1 bits long, .2 - value. Checks if the value is in the range 1 ..= value
98-
Unegmod(u8, u8), // encodes at .0, .1 bits long, -value % (1 << .1). Checks if the value is in the range 0 .. value
99-
Usumdec(u8, u8), // encodes at .0, .1 bits long, the value of the previous arg + the value of the current arg - 1
100-
Ufields(&'static [u8]), // an immediate, encoded bitwise with the highest bit going into field 0, up to the lowest going into the last bitfield.
93+
94+
/// format: `(pos, len)`
95+
/// `immediate` is in the range `0 .. (1<<len)`.
96+
/// `immediate` is encoded directly in a bitfield of length `len` at offset `pos`.
97+
Ubits(u8, u8),
98+
/// format: `(pos, len, shift)`
99+
/// `immediate >> shift` is in the range `0 .. (1 << len)`. Bottom `shift` bits are zero.
100+
/// `immediate >> shift` is encoded directly in a bitfield of length `len` at offset `pos`.
101+
Uscaled(u8, u8, u8),
102+
/// format: `(pos, [options])`
103+
/// `immediate` is one of the options in `options`.
104+
/// the index of `immediate` in options is encoded directly in a bitfield at offset `pos`.
105+
Ulist(u8, &'static [u16]),
106+
/// format: `(pos, min, max)`
107+
/// `immediate - min` is in the range `0 ..= max - min`.
108+
/// `immediate - min` is encoded in a bitfield starting at `pos`
109+
Urange(u8, u8, u8),
110+
111+
/// format: `(pos, len)`
112+
/// `immediate` is in the range `1 ..= (1 << len)`.
113+
/// `(1 << len) - value)` is encoded in a bitfield of length `len` at offset `pos`.
114+
Usubone(u8, u8),
115+
/// format: `(pos, len)`
116+
/// `immediate`is in the range `0 .. (1 << len)`.
117+
/// `(1 << len) - 1 - value)` is encoded in a bitfield of length `len` at offset `pos`.
118+
Usubzero(u8, u8),
119+
/// format: `(pos, len)`
120+
/// `immediate` is in the range `0 .. (1 << len)`.
121+
/// `(-value) & ((1 << len) - 1)` is encoded in a bitfield of length `len` at offset `pos`.
122+
Usubmod(u8, u8),
123+
/// format: `(pos, len)`
124+
/// `immediate` is in the range `1 ..= (1 << len) - prev_arg`
125+
/// `immediate + prev_arg - 1` is encoded in a a bitfield of length `len` at offset `pos`
126+
Usum(u8, u8),
127+
/// format: `([offsets])`
128+
/// `immediate is in the range `0 .. (1 << offsets.len())`
129+
/// `immediate` is encoded with bit N of the number at offsets[N]
130+
Ufields(&'static [u8]),
101131

102132
// signed immediate encodings
103-
Sbits(u8, u8), // encodes a signed immediate starting at bit .0, .1 bits long
104-
Sscaled(u8, u8, u8), // encodes a signed immediate, starting at bit .0, .1 bits long, shifted .2 bits to the right before encoding
105-
106-
// bit slice encodings. These don't advance the current argument. Only the slice argument actually encodes anything
107-
BUbits(u8), // checks if the pointed value fits in the given amount of bits
108-
BUsum(u8), // checks that the pointed value fits between 1 and (1 << .0) - prev
109-
BSscaled(u8, u8),
110-
BUrange(u8, u8), // check if the pointed value is between min/max
111-
Uslice(u8, u8, u8), // encodes at .0, .1 bits long, the bitslice starting at .2 from the current arg
112-
Sslice(u8, u8, u8), // encodes at .0, .1 bits long, the bitslice starting at .2 from the current arg
133+
134+
/// format: `(pos, len)`
135+
/// `immediate + (1 << (len - 1))` is in the range `0 .. (1<<len)`.
136+
/// `immediate` is encoded directly in a bitfield of length `len` at offset `pos`.
137+
Sbits(u8, u8),
138+
/// format: `(pos, len, shift)`
139+
/// `(immediate >> shift) + (1 << (len - 1))` is in the range `0 .. (1 << len)`. Bottom `shift` bits are zero.
140+
/// `immediate >> shift` is encoded directly in a bitfield of length `len` at offset `pos`.
141+
Sscaled(u8, u8, u8),
142+
143+
// pure validation encodings. These just check some precondition of the current argument, and don't advance to the next.
144+
145+
/// format: `(len)`
146+
/// `immediate` is in the range `0 .. (1<<len)`.
147+
CUbits(u8),
148+
/// format: `(len)`
149+
/// `immediate` is in the range `1 ..= (1 << len) - prev_arg`
150+
CUsum(u8),
151+
/// format: `(len, shift)`
152+
/// `(immediate >> shift) + (1 << (len - 1))` is in the range `1 ..= (1 << len)`. Bottom `shift` bits are zero.
153+
CSscaled(u8, u8),
154+
/// format: `(min, max)`
155+
/// `immediate - min` is in the range `0 ..= max - min`.
156+
CUrange(u8, u8),
157+
158+
// bit slice encodings. These encode part of a value
159+
160+
/// format: `(pos, len, offset)`
161+
/// `immediate >> offset` is encoded in a bitfield of length `len` at offset `pos`.
162+
Uslice(u8, u8, u8),
163+
/// format: `(pos, len, offset)`
164+
/// `immediate >> offset` is encoded in a bitfield of length `len` at offset `pos`.
165+
Sslice(u8, u8, u8),
113166

114167
// special immediate encodings
115168
Special(u8, SpecialComm),

0 commit comments

Comments
 (0)