Skip to content
New issue

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

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

Already on GitHub? # to your account

minor infidelity when lifting clz #374

Closed
regehr opened this issue Nov 7, 2019 · 0 comments
Closed

minor infidelity when lifting clz #374

regehr opened this issue Nov 7, 2019 · 0 comments
Assignees
Labels
aarch64 Related to ARM AARCH64 lifting support bug

Comments

@regehr
Copy link

regehr commented Nov 7, 2019

so LLVM's cttz and ctlz intrinsics have a flag to indicate whether the behavior should be undefined when the main argument is zero.
my understanding is that arm64's clz is defined in the case of zero argument, meaning that clz should be lifted to ctlz x, false
however, anvill/remill lift clz to ctlz x, true

in other words, this function:

0000000000000000 <slice>:
   0:	dac00008 	rbit	x8, x0
   4:	dac01100 	clz	x0, x8
   8:	d65f03c0 	ret

expressed like this:

{
  "os": "linux", 
  "functions": [
    {
      "return_stack_pointer": {"register": "SP", "type": "L", "offset": 0}, 
      "name": "slice", 
      "parameters": [
        {"register": "X0", "type": "l"}
      ], 
      "return_address": {"register": "X0", "type": "L"}, 
      "return_values": [
        {"register": "X0", "type": "l"}
      ], 
      "address": 0
    }
  ],
  "arch": "aarch64",
  "stack": {"size": 24576, "start_offset": 4096, "address": 87960930222080},
  "memory": [
    {
      "is_writeable": false, 
      "data": "0800c0da0011c0dac0035fd6",
      "is_executable": true,
      "is_readable": true,
      "address": 0
    }
  ]
}

decompiles to this:

define i64 @slice(i64) local_unnamed_addr #0 {
  %2 = tail call i64 @llvm.bitreverse.i64(i64 %0) #3
  %3 = tail call i64 @llvm.ctlz.i64(i64 %2, i1 true) #3, !range !0
  %4 = tail call %struct.Memory* @__remill_function_return(%struct.State* nonnull undef, i64 0, %struct.Memory* null) #3
  ret i64 %3
}

the ARM code is defined for argument zero whereas the LLVM code evaluates to poison in this case.

the fix is trivial: when lifting this ARM instruction, set the UB flag to false

@regehr regehr changed the title minor infidelity when lifting cttz minor infidelity when lifting clz Nov 7, 2019
@pgoodman pgoodman self-assigned this Nov 7, 2019
@pgoodman pgoodman added aarch64 Related to ARM AARCH64 lifting support bug labels Dec 11, 2019
pgoodman added a commit that referenced this issue Nov 5, 2020
@pgoodman pgoodman closed this as completed Nov 5, 2020
pgoodman pushed a commit that referenced this issue Nov 5, 2020
* New x86 instructions

* Add some isels

* Fixes Issue #376

* Fixes Issue #433. Thanks @adahsuzixin for the semantics and tests

* Fixes Issue #374

* Minor fix to the semantics for VINSERTF128, it should only look at the low bit of imm8

* Minor fixes for sparc isel naming
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
aarch64 Related to ARM AARCH64 lifting support bug
Projects
None yet
Development

No branches or pull requests

2 participants