aboutsummaryrefslogtreecommitdiff
path: root/CHANGELOG
blob: b4deece80680a12790621e50d909574f82c25b2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
## unreleased
* fix incorrect old yaxpeax-arch version selection for ffi crates

## 1.1.5
* fix several typos across crate docs - thank you Bruce! (aka github user waywardmonkeys)
* optimizations (mostly code motion) for hot codepaths
  - large `match`-based decode tables have been outlined to 256-entry arrays.
    this makes for slicely nicer inlining in `read_with_annotations`.
  - vex/evex decoding in 64-bit decoding now shares more code. this seems to
    aid code cache friendliness when prefixes must be read.
  - added a fast path for operand reading for the more-likely cases of
    [64-bit]: {0x66,rex}{<opcode>,0x0f-<opcode>}
    [32-bit]: {0x66}{<opcode>,0x0f-<opcode>}
    [16-bit]: {0x66}{<opcode>,0x0f-<opcode>}

    in particular, this avoids checking for instruction length overflows and
    some bounds checks when we aren't handling a pessimal case of many-prefixed
    instructions. if an instruction has multiple prefixes, decoders fall back
    to normal read-in-a-loop-until-length-limit-reached decoding.
* `Makefile` at the crate root now exercises `yaxpeax-x86` builds and tests under:
  - default features (fmt, std)
  - no-std + fmt
  - no-std and no-fmt
* fix several issues prohibiting builds of the crate with no-std +fmt
  configurations; the required Display impl for field annotation would simply not
  compile in no-fmt builds. it is now a minimal implementation to comply with the
  goals of `no-fmt`: "avoid as much extra code and data for formatting
  instructions as possible". two dozen bytes for a likely-DCE'd codepath should
  be ok.
* adjust test structure so that exhaustive tests can be `#[ignored]` and
  explicitly run anyway for completeness. this means the ignored at&t tests now
  are both ignored and appear to succeed when run.
* support `9a` encoding of `callf` with absolute segment/address operand
  - this encoding is only present in 32-bit and 16-bit modes

## 1.1.4
* fix reachable unreachable under `DisplayStyle::C` in 64-, 32-, and 16-bit modes
* add fuzz target to cover `DisplayStyle::C` formatter for 64-, 32-, and 16-bit modes

## 1.1.3
* fix reachable unsoundness via `RegSpec` helper functions
  - helpers should only permit creating valid `RegSpec` structs, but three
    helpers would permit out-of-range register numbers; `mask` registers in 16-
    and 32-bit modes, and `rex byte` registers in 64-bit modes.
  - when displaying an invalid `RegSpec`, for some out-of-range mask registers,
    the displayed register name could be chosen as arbitrary const data
    interpreted as a pointer/length pair
* fix incorrect (non-present!) memory size for f30f1e-style `nop`.
  - this would decode without error, but produce an instruction with memory
    operand and memory size of `0`. if formatted, yaxpeax-x86 panics.
* add in-tree `cargo fuzz` targets for decoding and displaying instructions.
  neither of these operations should ever panic.
* fix incorrect disassembler used in x86-16 doc comments

and thank you to @5225225 (https://github.com/5225225) for the bug reports
handled in 1.1.2 and 1.1.3, as well as the nudge to start using `cargo fuzz`.

## 1.1.2
* fix panic when evex instructions with compressed displacements are decoded in
  debug builds

## 1.1.1
* support `endbr64` and `endbr32`
  - these are interpretations of `nop` (`0f1e` wide nop), so the only issue
  with for users <1.1.1 will be `yaxpeax-86` decoding `nop` instead.
* export `InstructionDisplayer`
  this fixes an issue where crate docs would have dead links for the return
  value of public APIs. it also allows callers to write name of what
  `display_with` returns in their code, which hopefully isn't too useful but
  shouldn't be impossible.

## 1.1.0

* implement `AnnotatingDecoder` from `yaxpeax-arch=0.2.6` and later.
  this is a relatively involved addition. for rustc reasons, there are several
  additional `inline(always)` attributes applied to keep non-annotating decoder
  calls yielding the same generated code (and performance) as before.

  annotations are produced for much but not all of 16-, 32-, and 64-bit x86,
  describing prefixes, opcodes, operand encoding, and for more common
  instructions, operand encoding as well. descriptions provided are described
  by the `FieldDescription` struct in all architectures. `id` generally matches
  some kind of parse order for the instruction, typically the order that
  `yaxpeax-x86` considers bit fields in decoding an instruction. prefixes will
  have lower id than opcodes, opcodes will have lower id than operands,
  immediates will have the highest id due to being last values read in an
  instruction.

  between prefixes, opcodes, and operands, "Boundary" field descriptions are
  reported as a hint to library clients that a logical grouping of descriptions
  has ended.

* `pub const fn` builders for all general-purpose registers, segment registers, and ip/flags registers.
  - this corrects a spotty and inconsistent set of builders filled in on-demand.
* `DisplayStyle::Intel` now shows relative offsets as `$+0xXX`, rather than `0xXX`.
  - this corrects an ambiguity with instructions like `jz 0x1234`, where `jz`
    on x86 is _only_ relative branches, but the displayed syntax is ambiguous
    about being a relative or absolute address.
  - `DisplayStyle::Intel` is how `impl Display for Instruction` works, so
    typical `Display` use is also fixed.
* `push`, `pop`, `call`, and `ret` now report `mem_size` in all cases.
  - earlier, these instructions only reported a `mem_size` if their operand was a memory access.
  - for `call`, in 32- and 16-bit modes the reported memory size may describe
    the *read*, not the corresponding write of pushing `{e}ip` to the stack.
    documentation has been added to `mem_size` more specifically describing
    this circumstance.
* correct `rex.b` incorrectly applying to the `*ax` register - `4f91` is `xchg rax, r9`, not `xchg r8, r9`.
* correct `nop` incorrectly ignoring `rex.b` - `4190` is `xchg rax, r8`, not `nop`.
* `DisplayStyle::C` now has rules to nicely display `jCC`, `jmp`, `call`, `loop*`, and `j*cxz` instructions.

## 1.0.4

in 64-, 32-, and 16-bit modes:
  * fix incorrect decoding of `scas`; memory access is through `*di` not `*si`.
  * fix incorrect segment register for `scas` memory operand; `es` segment is always used.
  * fix incorrect decoding of some 67-prefixed string instructions: `movs`, `scas`, `lods`, `stos`, `cmps`.
    - a 67-prefix selects an alternate addressing mode. in 64-bit mode, this
      selects 32-bit registers for addressing, 32-bit selects 16-bit registers,
      and 16-bit selects 32-bit registers. the decoder had ignored the 67 prefix
      on these instructions.

in 32- and 16-bit modes:
  * fix incorrect decoding of 16-bit memory accesses with modrm where mod=00 and mmm=110.
    - the memory access from this modrm is a disp16 memory access, which the
      decoder reports. the decoder would then not read the subsequent 16-bit
      displacement. this would typically result in a `Displacement(0)` operand,
      and incorrect following instructions.

## 1.0.3

* fix a few broken doc links, added example of yaxpeax-x86 usage through yaxpeax-arch traits

## 1.0.2
* remove a stale line from README

## 1.0.1
* fix a broken docs link in README

## 1.0.0
* `avx512` support
* `avx2` support
* `avx` support
* real-mode (x86_16) support
* ffi-friendly packaging of decoders for 16-bit, 32-bit, and multi-arch uses
* added `Instruction::mem_size()` to query the size of an instruction's memory access
* `xacquire`/`xrelease` support
* `AMD` `sev_snp` support
* `pconfig`/Total Memory Encryption support
* `Intel` `keylocker` support
* removed `MOVSX_b`, `MOVSX_w`, `MOVZX_b`, and `MOVZX_w` - these differentiations are now described by `mem_size` and the `MOVSX`/`MOVZX` opcodes generally
* `PartialEq` impl for `Instruction` and all contained structures
* expose more details of an instruction's prefixes, and which prefixes are actually present on the instruction

## 0.2.2
* fix rendering error in `ShowContextual` impl with `&[Option<String>]` overrides
  - would in some circumstances incorrectly print stale data if an `Instruction` was reused for decoding.
    no impact on logical correctness, but certainly made for awkward disassembly in some cases.

## 0.2.1
* update `yaxpeax-arch` dep to 0.0.5
  - no external-facing changes for this, but `yaxpeax-arch 0.0.5` uses `crossterm` for cross-platform terminal coloring
* clean up a few warnings that made it into 0.2.0?

## 0.2.0
### features!
* fuzz against mishegos and fix many bugs that made obvious
  - duplicate and redundant f2, f3, and 66 prefixes on 0f-type opcodes are now
    handled "right", assuming xed as a source of truth. almost all of these cases
    are undefined by the intel and AMD manuals, but it seems unlikely that
    capstone is correct with respect to cpu interpretation while xed is
    incorrect.
* public `enum`s are now `#[non_exhaustive]`. these are `Operand`, `Opcode`, and `DecodeError`.
  - `Operand` is not expected to vary, but might.
  - `Opcode` will grow new variants for every extension.
  - `DecodeError` will probably not change, but no guarantees.
* add a notion of display styles for instructions, see `Instruction::display_with`. currently there are two styles:
  - `DisplayStyle::Intel` produces intel-like syntax for instructions
  - `DisplayStyle::C` produces C pseudocode-ish syntax for instructions
    - as an example, `xor eax, [rax]` is rendered as `eax ^= [rax]`.
  - `DisplayStyle::Att` is one potential future style, but not yet implemented
* `fmt`-related code and the `display` module are now optional on the `fmt` feature
  - this is to support minimal builds for decoders in non-formatting circumstances. `yaxpeax-x86` long mode is still 65kb there.
* improved packaging of ffi-friendly bindings in `ffi/`
  - architectures have standalone libraries for each of `long_mode`, `protected_mode`, and `real_mode` (last still to be implemented)
  - improved `ffi/` build instructions to describe how to build minimal-size `.so` and `.a` archives for linking
* `ffi/multiarch` is intended to be a single package for all architectures, but currently does not fulfil this role

### decode fixes
* segment prefixes (`cs`, `ds`, `ss`, `es`) are now properly ignored in long mode
* `lock xchg` now decodes correctly (operands were in reversed order and so memory "destinations" were treated as memory sources)
* some missing sse instructions are now supported (`blendps`, `blendpd`, `pclmulqdq`)
* some missing avx instructions are now supported (`vorpd`, `vorps`, `vandpd`, `vandps`, `vandnpd`, `vandnps`, `vpmaxuw`)
* prefetch instructions with register operand are interpreted as `nop`, not `#UD`
* `mov` to control or debug registers that are statically known to `#UD` now produce `DecodeError::InvalidOperand`
* `salc` is now rejected. it was accepted on a whim, and i am fickle.
  - realistically, this should be behind a decoder flag and accepted by
    default, but this makes fuzzing somewhat easier and isn't an instruction
    you'd expect to see in a modern x86 binary. see the summary at the end of
    this section for some thoughts on decoder flags...

### new ISA extension support!
* 3dnow is 3d-supported-now
* `sse4a` is now supported
* `gfni` extensions are now supported
* `ptwrite` extensions are now supported
* `cet` (`c`ontrol-flow `e`nforcement `t`echnology) extensions are now supported
* `invpcid` extensions are now supported
* `tdx` extensions are now supported
* `waitpkg` extensions are now supported
* `uintr` extensions are now supported
* `tsxldtrk` extensions are now supported
* `ud0`, `ud1`, and `ud2` are now supported - `ud2e` which was never real, is actually `ud1`
* `movdir` extensions are now supported
* `key locker` extensions are now supported
* `enqcmd` extensions are now supported

### architecture support
* all above changes apply both to `long_mode` and `protected_mode`.
  `protected_mode` may accept some 64bit-only instructions incorrectly. beware.

### thoughts?
folks, i'm out of feature bits in `InstDecoder`. there are too dang many x86
extensions. in the happy case, rustc knows that the provided decoder always
compares equal to `InstDecoder::default()` so it can be made an arbitrarily
large byte array. but i continue to be in awe of how much they put in the
computer. as things stand, new extensions are not categorized into
`InstDecoder` flags, but since there is a way to implement additional bits
without causing overhead in the happy path, this feature will probably continue
being supported in the future.

### unsafe
there are still a handful of `unsafe {}` uses in `yaxpeax-x86` for performance
reasons. i tried removing arms in matches by making the last meaningful arm,
often something like:
```
8 => { /* handle 8-byte operand */ }
```
into a general catchall arm and deleting the `unreachable_unchecked`, like:
```
_ => { /* handle 8-byte operand */ }
```
but this also caused a ~5% regression in performance. this makes sense, since
`unreachable_unchecked` is stronger in saying that other values (`3`, `5`, `6`,
`7`, ...) will _not_ occur, but `_` doesn't disallow them and likely produces
jump tables for no good reason. maybe this can be solved some other way, one
day...

## 0.1.5
* fix several issues around 0f01* opcode decoding;
  - AMD-only `monitorx`, `mwaitx`, `clzero`, and `rdpru` are now supported
  - `swapgs` is invalid in non-64-bit modes
  - `rdpkru` and `wrpkru` were incorrectly decoded when modrm bits were not `11`
* small performance tweaks. read_imm_signed is now inline(always) and some
  pre-decode initialization is a bit better-packed
* `xchg {r,e,}ax, reg` was not supported! it's supported now.

## 0.1.4
* [long mode only]: fix decoding of rex-prefixed modrm+sib operands selecting index 0b100 and base 0b101
  - for memory operands with a base, index, and displacement either
    the wrong base would be selected (register number ignored, so only
    `*ax` or `r8*` would be reported), or yaxpeax-x86 would report a
    base register is present when it is not (`RegIndexBaseScaleDisp`
    when the operand is actually `RegScaleDisp`)

thank you to Evan Johnson for catching and reporting this bug!

## 0.1.3
* fix 0x80-opcode instructions not having an opcode
  - this meant that for example `lock xorb [rax], 0` would decode as invalid

## 0.1.2
* expose constructors for `RegSpec` in both `long_mode` and `protected_mode`
* expose a const `RegSpec::RIP`
  - most useful for matching `Operand::RegDisp(RegSpec::RIP, disp)` in patterns, really

## 0.1.1
* add `long_mode::register_class` and `protected_mode::register_class` where
  `RegisterClass` constants for each register class are defined.
  - without these, the only way to distinguish register classes would be string compares. bad. sorry!

## 0.1.0
* port `long_mode` improvements to `protected_mode` decoder
  - real mode will wait until another day
* support undocumented instruction `salc`
* fix segment registers being numbered wrong
  - this is relevant only for mov to/from segments
* support x86_32 `push <segment>``/`pop <segment>`
* support x86_32 `pusha`/`popa`
* support x86_32 BCD instructions
  - for `aam`/`aad`, the undocumented `amx` and `adx` forms are used in all cases, including when the base is 10
* begin some proper documentation for public items

/!\ BREAKING CHANGES /!\
* `RegisterBank` is no longer public. `RegisterClass` should be a suitable
  replacement, accessible via `reg.class()`, with the register class name
  available by `reg.class().name`, and size available by `reg.class().width()`.
  `reg.width()` still works, and just forwards to `reg.class().width()`.
* the field `opcode` of `Instruction` is no longer public. it can now be accessed by `inst.opcode()`.

## 0.0.15

* the `x87` instruction set is now fully supported
  - textual disassembly differs slightly from other decoders in that
    yaxpeax-x86 does not prefer using `st` in place of `st(0)`
* do not decode `into` in 64-bit mode
* support `vmread`, `vmwrite`
* support `iret`/`iretd`/`iretq`
* support `enter`
* support `cmc` and `int1`
* support `loopz`, `loopnz`, `jecxz`
* support `maskmovq`, `movnti`, and `movntq`
  - this brings full support to non-vex-coded x86 instructions
* reject excessively-long instructions
* reject reg-reg encodings where instructions forbid those operands
* correctly handle `mov [0xoffset], ax` and `mov ax, [0xoffset]`
  - offset had been read with incorrect size
* `vpsrlw`, `vpermq`, `vpminsq`, `vpsrlq`, `vextractf128`, `vinserti128`
* reorganize likely decoding paths for a smidge more speed

## 0.0.14

* `netburst` supported `cmpxchg16b` from its first x86_64 incarnation. since no
uarch in `long_mode` had declared `cmpxchg16b` support, no uarch-specific Intel
decoder supported `cmpxchg16b`.

## 0.0.13

* the Intel microarchitecture is named `Penryn`, not `Peryn`.

## 0.0.12

* fix improper decode of `sib` memory operand when `rex.x` is set and index is `0b100`
  - functionally: instructions which should have had a memory operand like
    `[rax + r12 + disp]` were missing `r12`
* add instruction set extensions: `SHA`, `BMI1`, `BMI2`, `XSAVE`, `RDRAND`,
  `RDSEED`, `CMPXCHG{8,16}B` `ADX`, `SVM`, `MOVBE`, `PREFETCHW`, `TSX`, and
  `F16C`
* add `RDFSBASE`, `RDGSBASE`, `WRFSBASE`, `WRGSBASE`
* builders for per-uarch x86_64 instruction decoders, see `yaxpeax_x86::long_mode::uarch::{intel, amd}`
* builders for per-uarch x86_32 instruction decoders, see `yaxpeax_x86::protected_mode::uarch::{intel, amd}`

## 0.0.11

* fix mis-named 'cbd' instruction, which should be 'cwd'
* add `Operand::width` to query the width of an x86 access
  - this is wrong for many memory operands, which require deeper changes
* bump `yaxpeax-arch` to 0.0.4, which yields a breaking change in `Self::Unit` of `LengthedInstruction
* `Prefixes::rep` is now public, allowing users to query if a decoded instruction has a rep prefix

## 0.0.10

same as 0.0.9, but with a warning fixed.

## 0.0.9

added `protected_mode` for 32-bit instruction decoding. BCD instructions not yet supported.

## 0.0.8

same as 0.0.7, but with a readme in the crates.io page.

## 0.0.7

`sse` and `sse2` support are mostly complete.
`jmp reg` erroneously decoded to 32-bit registers without `rex.w`.
`callf` could erroneously decode as having a register operand.
more comprehensive, if yet insufficiently tested, avx decoding.
support `vmclear` and `vmxon`, vmx still incomplete.

## 0.0.6

addressing modes using a sib byte with displacement != 0 were wrongly reported as having no displacement.

## 0.0.5

history basically starts here.

* impl Ord and PartialOrd on RegSpec and RegisterBank
* `RegSpec::name` to get `&'static str` labels for registers
* support `in` and `out` instructions

## 0.0.4 - 0.0.2

seriously stop, just don't use these versions

just bumps to use newer `yaxpeax-arch` since this is all wildly unstable