This is a fix for #424. The fix consists in splitting the logic for
equality tests based on the value of isTrue. I have separated it as its
own function as it's needed for two branches, and Haskell lacks binding
or-patterns.
This builds on top of the work in GaloisInc/elf-edit#45. For now, I only add
support for a select few relocation types, leaving the rest as future work.
This paves a way for an eventual fix for #414.
Given some symbolic value, @x@, we'd like to compute its
possible upper and lower bounds after it is truncated to @w@ bits.
To do this, we first find the bound of x by (recursively) calling `exprRangePred`.
This bound is a statement of the following form (see `RangePred` for more info):
"r bits of x are bounded between @low@ and @high@".
Then, we check the following:
- If x has a bound (r, l, w)
AND
- If r is less than or equal to w
=> Pass-through the bound (r, l, w)
Otherwise, we deem x "unbounded"
Declaring x unbounded in the second case seems to throw away useful
information that causes many jump tables to remain unclassified.
We attempt to improve on that in this commit.
Consider an example where x is bounded by (64, 0, 10)
(that is, the 64 bits of x are constrained to be between 0 and 10)
and we want to find the bound of truncating x to 8 bits.
With the current logic, since 64 > 8, we'd declare x unbounded.
However, the bound (8, 0, 10) should also be valid: if 64 bits of
x are bounded to [0, 10], then surely 8 bits of x also lie between
0 and 10.
If the upper bound is instead larger than the largest 8-bit value, we
can truncate it to the largest value.
For example, (64, 0, 10000) becomes (8, 0, 255).
Instead of losing the bound completely, we're able to tighten it!
For some reason we were very conservative in our support or abstract
operations over the processor state in the `RegisterUse` analysis.
In particular, we were failing to process code such as:
r23 := (bv_and r21 (0xfffffffffffffff0 :: [64]))
whose goal is to align the value in r21 at a 16-byte boundary.
This resulted in us failing to analyze some code that was realigning its
stack pointer. With this change, the same code succeeds at propagating
the abstract stack pointer offset forward.
This patch contains a handful of tweaks needed to make the libraries in the
`macaw` repo build with GHC 9.6:
* GHC 9.6 bundles `mtl-2.3.*`, which no longer re-exports `Control.Monad`,
`Control.Monad.Trans`, and similar modules from `mtl`-related modules. To
accommodate this, various imports have been made more explicit.
* I have disambiguated a use of `Data.Parameterized.NatRepr.withKnownNat` in
`macaw-aarch32` to avoid clashing with a newly exported function of the same
name in `GHC.TypeNats`.
* I have bumped various upper version bounds on `doctest`,
`optparse-applicative`, and `what4` to allow building these libraries with
GHC 9.6.
* I have bumped the following submodules to bring in GHC 9.6–related changes:
* `asl-translator`: GaloisInc/asl-translator#53
* `crucible`: GaloisInc/crucible#1102
* `dwarf`: GaloisInc/dwarf#6
* `elf-edit`: GaloisInc/elf-edit#38
* `flexdis86`: GaloisInc/flexdis86#54
* `grift`: GaloisInc/grift#9
* `llvm-pretty`: elliottt/llvm-pretty#112
* `llvm-pretty-bc-parser`: GaloisInc/llvm-pretty-bc-parser#225
* `semmc`: GaloisInc/semmc#80
* `what4`: GaloisInc/what4#235
This is cargo-culted from the `*.Panic` module of a similar name in
`macaw-aarch32`. This will be useful in a subsequent commit in which we replace
some unreachable calls to `fail` with `panic`.
This extends `Data.Macaw.Symbolic.Testing` in `macaw-symbolic` to be able to
handle binaries that depend on shared libraries. This is fully functional for
the x86-64 and AArch32 symbolic backends, and I have added test cases to the
respective repos demonstrating that it works. (The PowerPC backend is not yet
supported. At a minimum, this is blocked on GaloisInc/elf-edit#35.)
To implement this, I also needed to add some additional infrastructure to
`macaw-base` (I put this infrastructure here as it doesn't depend on any
Crucible-specific functionality):
* `Data.Macaw.Memory.ElfLoader.DynamicDependencies`: a basic ELF dynamic
loader that performs a breadth-first search over all `DT_NEEDED` entries
that an ELF binary depends on (both directly and indirectly).
* `Data.Macaw.Memory.ElfLoader.PLTStubs`: a collection of heuristics for
detecting the addresses of PLT stubs in a dynamically linked binary.
It is worth noting that shared libraries are rife with nuance and subtlety,
and the way `macaw` models shared libraries is not 100% accurate. I have
written a length `Note [Shared libraries]` in `Data.Macaw.Symbolic.Testing`
to describe where corners had to be cut.
Fixes#318.
This:
* Bumps the `elf-edit` submodule to bring in the changes from
GaloisInc/elf-edit#34.
* Updates `Data.Macaw.Memory.ElfLoader` to consolidate the symbol table logic
with the corresponding functions from `elf-edit`.
Fixes#277.
We already have support for `R_X86_64_COPY` relocations, so adding support
for `R_ARM_COPY` on the AArch32 side is straightforward.
This is related to #47, although this is not a full fix for the issue.
It turns out that we have to be more conservative with tail call identification,
as incorrectly identifying a block as the target of a tail call (instead of a
branch) can cause other branch classifiers to fail if that block is the target
of another jump.
Ultimately, we will need to give up some tail call recognition (since they are
in general indistinguishable from jumps), and instead only identify known call
targets as tail call candidates.
With additional global analysis we could do better.
Fixes#294
The bug arose in the handling of `StackOffsetAbsVal`, which track an abstraction
of references relative to the stack pointer. The offsets in `StackOffsetAbsVal`
are `Int64`; they are signed because references are both above and below the
stack pointer. The code constructing new values of this type was incorrectly
zero-extending new offsets instead of sign extending them. This did not matter
on 64 bit architectures, as it happened to result in the same values. It
substantially corrupted the abstract stack on PowerPC 32. It did not seem to
affect AArch32, but that is likely just due to luck in compiler code generation
that does not require this level of precision in the abstract stack.
The resulting errors manifest in the `absEvalCall` function. Because of the lack
of sign extension in `StackOffsetAbsVal`s, it made the current stack pointer
look like a huge number, which caused *all* stack entries to be dropped after
function calls.
This fix simplifies the stack offset abstract value computation substantially
and ensures that signs are extended correctly. The commit adds a PowerPC32 test
case that only passes with this fix.
GHC 9.2 adds `-Wincomplete-uni-patterns` to `-Wall`, which uncovers a slew of
previously unnoticed warnings in `macaw`. This patch fixes them, mostly by
adding explicit fall-through cases.
In `base-4.16.*`, `Nat` is now a type synonym for `Natural`, and `GHC.TypeLits`
now re-exports `Natural`. This causes a `-Wunused-imports` warning in
`macaw-base` as a consequence. I fixed the warning by tightening up the imports
slightly.
The tail call classifier came after the jump classifier, which was a problem because it is less strict than the tail call classifier, meaning it would always fire. This commit moves direct jump to be the last classifier applied, giving the others a chance.
Includes a test case in the ARM backend.
This requires some updates to some of the expected test results, as a few blocks are now classified as tail calls that were
plain jumps before. They really could be considered either. I think it would be nice if these could be classified as jumps instead, but the reason they are flagged as tail calls is mostly down to the fact that their surrounding context is so simple that either interpretation works.
Correcting this would require some heuristics based on additional analysis passes.
The test harness for macaw symbolic required a few changes because the new detection of some jumps as tail calls introduces new calls into the symbolic test suites. However, the symbolic testing harness did not support calls before. Adding support required a bit of plumbing, including a more extensive code discovery pass.
Fixes#285
This bump the `elf-edit` submodule to bring in the changes from
https://github.com/GaloisInc/elf-edit/pull/29, which adds an additional
`VersionDefMap` argument to `elf-edit` to make it aware of version definitions.
This requires some changes to the API in `Data.Macaw.Memory.ElfLoader` to
accommodate.