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

Fix incomplete trap metadata due to multiple traps at one address. #2685

Merged
merged 1 commit into from
Feb 25, 2021

Conversation

cfallin
Copy link
Member

@cfallin cfallin commented Feb 24, 2021

If an instruction has more than one trap record associated with it (for
example: a divide instruction that has participated in load-op fusion,
so we have both a heap-out-of-bounds trap record due to its load and a
divide-by-zero trap record due to its divide op), the current MachBuffer
code would emit only one of the trap records to the sink.

Separately, divide instructions probably shouldn't merge loads, because
the two separate possible traps at one location might be confusing for
some embedders (certainly in Lucet). Divide seems to be the only case in
our current codegen where such merging might occur. This PR changes the
lowering to always force the divisor into a register.

Finally, while working out why trap records were not appearing, I had
noticed that isa::x64::emit_std_enc_mem() was only emitting heap-OOB
trap metadata for loads/stores when it had a srcloc. This PR ensures
that the metadata is emitted even when the srcloc is empty.

Note that none of the above presents a security or correctness problem;
trap metadata only affects the status that we return to the embedder
when a Wasm program terminates with a trap.

If an instruction has more than one trap record associated with it (for
example: a divide instruction that has participated in load-op fusion,
so we have both a heap-out-of-bounds trap record due to its load and a
divide-by-zero trap record due to its divide op), the current MachBuffer
code would emit only one of the trap records to the sink.

Separately, divide instructions probably shouldn't merge loads, because
the two separate possible traps at one location might be confusing for
some embedders (certainly in Lucet). Divide seems to be the only case in
our current codegen where such merging might occur. This PR changes the
lowering to always force the divisor into a register.

Finally, while working out why trap records were not appearing, I had
noticed that `isa::x64::emit_std_enc_mem()` was only emitting heap-OOB
trap metadata for loads/stores when it had a srcloc. This PR ensures
that the metadata is emitted even when the srcloc is empty.

Note that none of the above presents a security or correctness problem;
trap metadata only affects the status that we return to the embedder
when a Wasm program terminates with a trap.
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator cranelift:area:machinst Issues related to instruction selection and the new MachInst backend. cranelift:area:x64 Issues related to x64 codegen labels Feb 24, 2021
@cfallin cfallin merged commit ebbe626 into bytecodealliance:main Feb 25, 2021
@cfallin cfallin deleted the fix-multi-trap-metadata branch February 25, 2021 00:38
cfallin added a commit to bytecodealliance/lucet that referenced this pull request Feb 25, 2021
pchickey pushed a commit to bytecodealliance/lucet that referenced this pull request Feb 25, 2021
jameysharp added a commit to jameysharp/wasmtime that referenced this pull request Mar 13, 2024
In bytecodealliance#2426, @cfallin wrote:

> […] don't emit trap info unless an op can trap.
>
> This end result was previously enacted by carrying a SourceLoc on
> every load/store, which was somewhat cumbersome, and only indirectly
> encoded metadata about a memory reference (can it trap) by its
> presence or absence.

That PR changed both backends that existed at the time to check both the
source location and the memory flags to determine whether a memory
access could trap.

Then in bytecodealliance#2685, @cfallin wrote:

> Finally, while working out why trap records were not appearing, I had
> noticed that isa::x64::emit_std_enc_mem() was only emitting heap-OOB
> trap metadata for loads/stores when it had a srcloc. This PR ensures
> that the metadata is emitted even when the srcloc is empty.

However that PR did not apply the same change to other backends. Since
then, the pattern from bytecodealliance#2426 has been copied to new backends.

I believe checking the source location has been unnecessary since bytecodealliance#2426
and is now just a source of confusion at best, and possibly bugs at
worst. So this PR makes all targets match the behavior of the x64
backend.

In addition, this pattern was the only reason why source locations were
provided to any backend's emit state, so I'm removing that entirely.
The `cur_srcloc` field has been unused on x64 since bytecodealliance#2685.

This change is mostly straightforward, but there are two questionable
changes in the riscv64 backend:

- The riscv64 backend had one use of this pattern for a
  BadConversionToInteger trap. All other uses on all backends were for
  HeapOutOfBounds traps. I suspect that was a copy-paste bug so I've
  removed it just like all the others.

- The riscv64 `Inst::Atomic` does not have a MemFlags field, so this
  means the HeapOutOfBounds trap metadata is added unconditionally for
  such instructions.
github-merge-queue bot pushed a commit that referenced this pull request Mar 13, 2024
* cranelift: Remove srcloc from emit state on all targets

In #2426, @cfallin wrote:

> […] don't emit trap info unless an op can trap.
>
> This end result was previously enacted by carrying a SourceLoc on
> every load/store, which was somewhat cumbersome, and only indirectly
> encoded metadata about a memory reference (can it trap) by its
> presence or absence.

That PR changed both backends that existed at the time to check both the
source location and the memory flags to determine whether a memory
access could trap.

Then in #2685, @cfallin wrote:

> Finally, while working out why trap records were not appearing, I had
> noticed that isa::x64::emit_std_enc_mem() was only emitting heap-OOB
> trap metadata for loads/stores when it had a srcloc. This PR ensures
> that the metadata is emitted even when the srcloc is empty.

However that PR did not apply the same change to other backends. Since
then, the pattern from #2426 has been copied to new backends.

I believe checking the source location has been unnecessary since #2426
and is now just a source of confusion at best, and possibly bugs at
worst. So this PR makes all targets match the behavior of the x64
backend.

In addition, this pattern was the only reason why source locations were
provided to any backend's emit state, so I'm removing that entirely.
The `cur_srcloc` field has been unused on x64 since #2685.

This change is mostly straightforward, but there are two questionable
changes in the riscv64 backend:

- The riscv64 backend had one use of this pattern for a
  BadConversionToInteger trap. All other uses on all backends were for
  HeapOutOfBounds traps. I suspect that was a copy-paste bug so I've
  removed it just like all the others.

- The riscv64 `Inst::Atomic` does not have a MemFlags field, so this
  means the HeapOutOfBounds trap metadata is added unconditionally for
  such instructions.

* Filetests don't have srclocs so they get traps now
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:area:machinst Issues related to instruction selection and the new MachInst backend. cranelift:area:x64 Issues related to x64 codegen cranelift Issues related to the Cranelift code generator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants