haybale 0.7.2

Symbolic execution of LLVM IR, written in Rust
Documentation
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
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
# `haybale`: Symbolic execution of LLVM IR, written in Rust

[![crates.io](https://img.shields.io/crates/v/haybale.svg)](https://crates.io/crates/haybale)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/cdisselkoen/haybale/main/LICENSE)

`haybale` is a general-purpose symbolic execution engine written in Rust.
It operates on LLVM IR, which allows it to analyze programs written in C/C++,
Rust, Swift, or any other language which compiles to LLVM IR.
In this way, it may be compared to [KLEE], as it has similar goals, except
that `haybale` is written in Rust and makes some different design decisions.
That said, `haybale` makes no claim of being at feature parity with KLEE.

### Okay, but what is a symbolic execution engine?

A symbolic execution engine is a way of reasoning - rigorously and
mathematically - about the behavior of a function or program.
It can reason about _all possible inputs_ to a function without literally
brute-forcing every single one.
For instance, a symbolic execution engine like `haybale` can answer questions
like:

- Are there any inputs to (some function) that cause it to return 0? What are they?
- Is it possible for this loop to execute exactly 17 times?
- Can this pointer ever be NULL?

Symbolic execution engines answer these questions by converting each variable in
the program or function into a mathematical expression which depends on the
function or program inputs.
Then they use an SMT solver to answer questions about these expressions, such
as the questions listed above.

## Getting started

### 1. Install

`haybale` is on [crates.io](https://crates.io/crates/haybale), so you can simply
add it as a dependency in your `Cargo.toml`, selecting the feature corresponding
to the LLVM version you want:

```toml
[dependencies]
haybale = { version = "0.7.2", features = ["llvm-14"] }
```

Currently, the supported LLVM versions are `llvm-9`, `llvm-10`, `llvm-11`,
`llvm-12`, `llvm-13`, and `llvm-14`.

`haybale` depends (indirectly) on the LLVM and Boolector libraries.
* LLVM must be available on your system, in the version which matches the
selected feature. (For instance, if you select the `llvm-14` feature, LLVM 14
must be available on your system.) For more details and instructions on
installing LLVM and making sure Cargo can find it, see the [`llvm-sys`] README.
* For Boolector you have two options:
    * You can compile and install Boolector 3.2.1 on your system as a shared library. (Make sure you configure it as a shared library, e.g., using
    `./configure.sh --shared`, and install it, using `make install`.)
    * Or, you can enable the `haybale` feature `vendor-boolector`. With this
    option, Cargo will automatically download and build Boolector and statically
    link to it. E.g.,
      ```toml
      [dependencies]
      haybale = { version = "0.7.2", features = ["llvm-14", "vendor-boolector"] }
      ```
      This option probably only works on Linux and macOS, and requires standard
      build tools to be available on your system -- e.g., for Debian-based
      distributions, `build-essential`, `cmake`, `curl`, and `git`.

### 2. Acquire bitcode to analyze

Since `haybale` operates on LLVM bitcode, you'll need some bitcode to get started.
If the program or function you want to analyze is written in C, you can generate
LLVM bitcode (`*.bc` files) with `clang`'s `-c` and `-emit-llvm` flags:

```bash
clang -c -emit-llvm source.c -o source.bc
```

For debugging purposes, you may also want LLVM text-format (`*.ll`) files, which
you can generate with `clang`'s `-S` and `-emit-llvm` flags:

```bash
clang -S -emit-llvm source.c -o source.ll
```

If the program or function you want to analyze is written in Rust, you can likewise
use `rustc`'s `--emit=llvm-bc` and `--emit=llvm-ir` flags.

Note that in order for `haybale` to print source-location information (e.g.,
source filename and line number) in error messages and backtraces, the LLVM
bitcode will need to include debuginfo.
You can ensure debuginfo is included by passing the `-g` flag to `clang`,
`clang++`, or `rustc` when generating bitcode.

### 3. Create a Project

A `haybale` [`Project`] contains all of the code currently being analyzed, which
may be one or more LLVM modules.
To get started, simply create a `Project` from a single bitcode file:

```rust
let project = Project::from_bc_path("/path/to/file.bc")?;
```

For more ways to create `Project`s, including analyzing entire libraries, see
the [`Project` documentation].

### 4. Use built-in analyses

`haybale` currently includes two simple built-in analyses:
[`get_possible_return_values_of_func()`], which describes all the possible
values a function could return for any input, and [`find_zero_of_func()`],
which finds a set of inputs to a function such that it returns `0`.
These analyses are provided both because they may be of some use themselves,
but also because they illustrate how to use `haybale`.

For an introductory example, let's suppose `foo` is the following C function:

```c
int foo(int a, int b) {
    if (a > b) {
        return (a-1) * (b-1);
    } else {
        return (a + b) % 3 + 10;
    }
}
```

We can use `find_zero_of_func()` to find inputs such that `foo` will return `0`:

```rust
match find_zero_of_func("foo", &project, Config::default(), None) {
    Ok(None) => println!("foo can never return 0"),
    Ok(Some(inputs)) => println!("Inputs for which foo returns 0: {:?}", inputs),
    Err(e) => panic!("{}", e),  // use the pretty Display impl for errors
}
```

## Writing custom analyses

`haybale` can do much more than just describe possible function return values
and find function zeroes.
In this section, we'll walk through how we could find a zero of the function
`foo` above without using the built-in `find_zero_of_func()`.
This will illustrate how to write a custom analysis using `haybale`.

### ExecutionManager

All analyses will use an [`ExecutionManager`] to control the progress of the
symbolic execution.
In the code snippet below, we call [`symex_function()`] to create an
`ExecutionManager` which will analyze the function `foo` - it will start at
the top of the function, and end when the function returns. In between, it
will also analyze any functions called by `foo`, as necessary and depending
on the [`Config`] settings.

```rust
let mut em = symex_function("foo", &project, Config::<DefaultBackend>::default(), None);
```

Here it was necessary to not only specify the default `haybale`
configuration, as we did when calling `find_zero_of_func()`, but also what
"backend" we want to use.
The `DefaultBackend` should be fine for most purposes.

### Paths

The `ExecutionManager` acts like an `Iterator` over _paths_ through the function `foo`.
Each path is one possible sequence of control-flow decisions (e.g., which direction
do we take at each `if` statement) leading to the function returning some value.
The function `foo` in this example has two paths, one following the "true" branch and
one following the "false" branch of the `if`.

Let's examine the first path through the function:

```rust
let result = em.next().expect("Expected at least one path");
```

In the common case, `result` contains the function return value on this path,
as a Boolector [`BV`] (bitvector) wrapped in the [`ReturnValue`] enum.
Since we know that `foo` isn't a void-typed function (and won't throw an
exception or abort), we can simply unwrap the `ReturnValue` to get the `BV`:

```rust
let retval = match result {
    Ok(ReturnValue::Return(r)) => r,
    Ok(ReturnValue::ReturnVoid) => panic!("Function shouldn't return void"),
    Ok(ReturnValue::Throw(_)) => panic!("Function shouldn't throw an exception"),
    Ok(ReturnValue::Abort) => panic!("Function shouldn't panic or exit()"),
    ...
```

`result` could also be an `Err` describing an [`Error`] which was encountered
while processing the path. In this case, we could just ignore the error and
keep calling `next()` to try to find paths which didn't have errors. Or we
could get information about the error like this:

```rust
    ...
    Err(e) => panic!("{}", em.state().full_error_message_with_context(e)),
};
```

This gets information about the error from the program `State`, which we'll
discuss next. But for the rest of this tutorial, we'll assume that we got the
`Ok` result, and at this point `retval` is a `BV` representing the function
return value on the first path.

### States

For each path, the [`ExecutionManager`] provides not only the final result of
the path (either a`ReturnValue` or an `Error`), but also the final program
[`State`] at the end of that path.
We can get immutable access to the `State` with `state()`, or mutable access
with `mut_state()`.

```rust
let state = em.mut_state();  // the final program state along this path
```

To test whether `retval` can be equal to `0` in this `State`, we can use
`state.bvs_can_be_equal()`:

```rust
let zero = state.zero(32);  // The 32-bit constant 0
if state.bvs_can_be_equal(&retval, &zero)? {
    println!("retval can be 0!");
}
```

### Getting solutions for variables

If `retval` can be `0`, let's find what values of the function parameters
would cause that.
First, we'll add a constraint to the `State` requiring that the return value
must be `0`:

```rust
retval._eq(&zero).assert();
```

and then we'll ask for solutions for each of the parameters, given this constraint:

```rust
// Get a possible solution for the first parameter.
// In this case, from looking at the text-format LLVM IR, we know the variable
// we're looking for is variable #0 in the function "foo".
let a = state.get_a_solution_for_irname(&String::from("foo"), Name::from(0))?
    .expect("Expected there to be a solution")
    .as_u64()
    .expect("Expected solution to fit in 64 bits");

// Likewise the second parameter, which is variable #1 in "foo"
let b = state.get_a_solution_for_irname(&String::from("foo"), Name::from(1))?
    .expect("Expected there to be a solution")
    .as_u64()
    .expect("Expected solution to fit in 64 bits");

println!("Parameter values for which foo returns 0: a = {}, b = {}", a, b);
```

Alternately, we could also have gotten the parameter `BV`s from the `ExecutionManager`
like this:

```rust
let a_bv = em.param_bvs()[0].clone();
let b_bv = em.param_bvs()[1].clone();

let a = em.state().get_a_solution_for_bv(&a_bv)?
    .expect("Expected there to be a solution")
    .as_u64()
    .expect("Expected solution to fit in 64 bits");

let b = em.state().get_a_solution_for_bv(&b_bv)?
    .expect("Expected there to be a solution")
    .as_u64()
    .expect("Expected solution to fit in 64 bits");

println!("Parameter values for which foo returns 0: a = {}, b = {}", a, b);
```

## Documentation

Full documentation for `haybale` can be found [on docs.rs](https://docs.rs/haybale),
or of course you can generate local documentation with `cargo doc --open`.

## Compatibility

Currently, the official crates.io releases of `haybale` (`0.7.0` and later)
depend on Boolector 3.2.1 and LLVM 9, 10, 11, 12, 13, or 14,  selected via feature
flags `llvm-9` through `llvm-14`.
As of this writing, choosing an LLVM version has essentially no effect
on `haybale`'s features or interface; the only difference is the ability to
analyze bitcode generated with newer LLVMs. (And the LLVM 10+ versions
can process `AtomicRMW` instructions; see
[#12](https://github.com/PLSysSec/haybale/issues/12).)

For LLVM 8, you can try the `llvm-8` branch of this repo. This branch is
unmaintained, and is approximately at feature parity with `haybale` 0.2.1.
It may work for your purposes; or you can update to LLVM 9 or later and the
latest `haybale`.

LLVM 7 and earlier are not supported.

`haybale` works on stable Rust, and requires Rust 1.45 or later.

## Under the hood

`haybale` is built using the Rust [`llvm-ir`] crate and the [Boolector] SMT
solver (via the Rust [`boolector`] crate).

## Changelog

### Version 0.7.2 (Oct 26, 2023)

- Support for LLVM 14 via the `llvm-14` feature
- Fixed/improved support for a couple of intrinsics

### Version 0.7.1 (Oct 21, 2021)

- Support for LLVM 13 via the `llvm-13` feature
- `haybale` now requires Rust 1.45+ (previously 1.43 or 1.44)

### Version 0.7.0 (Aug 26, 2021)

- Support for LLVM 12 via the `llvm-12` feature
- New Cargo feature to vendor Boolector: automatically download, build, and
statically link Boolector as part of the `haybale` build process. See the
"Install" section of the README above.
- [`symex_function()`] now takes an additional argument `params`. You can use
this argument to specify constraints for the function parameters, or even
specify specific hardcoded values. Or, you can just pass `None` and get the
previous `haybale` behavior, treating all parameters as completely
unconstrained.
- [`find_zero_of_func()`] and [`get_possible_return_values_of_func()`] likewise
now take a `params` argument to specify constraints on function parameters.
- [`State`] has a new public field `proj` providing access to the [`Project`].
- Function hooks no longer take a `Project` parameter explicitly. Instead, you
can access the `Project` through the `proj` field of the `State` object.
- [`ExecutionManager`] has a new public method `.func()` which provides access
to the toplevel `Function`.
- [`State`] has a new public method `get_path_length()`, also available as the
toplevel function [`get_path_length()`].
- Updated `llvm-ir` dependency to 0.8.0, which results in minor breaking changes
to parts of `haybale`'s API, where `llvm-ir` types are exposed.

### Version 0.6.4 (Apr 22, 2021)

- Fix the build with Rust 1.51+ ([#16]https://github.com/PLSysSec/haybale/issues/16).
(Minimum Rust version for `haybale` remains unchanged: 1.43+ for LLVM 9 or 10
users, or 1.44+ for LLVM 11 users.)

### Version 0.6.3 (Oct 26, 2020)

- Fix the documentation build on [docs.rs]https://docs.rs/haybale
([#13]https://github.com/PLSysSec/haybale/issues/13)

### Version 0.6.2 (Oct 20, 2020)

- Support for LLVM 11 via the `llvm-11` feature
- [`get_possible_return_values_of_func()`] now handles void functions properly
([#10]https://github.com/PLSysSec/haybale/issues/10)
- Support LLVM `atomicrmw` instructions (only for LLVM 10+)
([#12]https://github.com/PLSysSec/haybale/issues/12)
- Support LLVM `freeze` instructions (which only exist in LLVM 10+)
- Built-in support for a few more Rust standard-library functions related to
panic handling
- [`State`] has a new public method [`get_bv_by_irname()`]
- LLVM 11 users need Rust 1.44+, due to requirements of `llvm-ir`. LLVM 9 or
10 users still need only Rust 1.43+.

### Version 0.6.1 (Sep 17, 2020)

- Both [`State`] and [`Project`] now have a method `size_in_bits()` which
gets the size of any `Type` in bits, accounting for the `Project`'s pointer
size and struct definitions. This is intended to replace `state.size()` and
`state.size_opaque_aware()`, both of which are now deprecated and will be
removed in `haybale` 0.7.0. Likewise, `state.fp_size()` was deprecated and
renamed to `state.fp_size_in_bits()`.
    - Note: these deprecated methods were actually removed in 0.7.1.

### Version 0.6.0 (Sep 1, 2020)

- `haybale` now supports both LLVM 9 and LLVM 10, using the same branch and
same crates.io releases.
When using `haybale`, you must choose either the `llvm-9` or the `llvm-10`
feature.
- Updated `llvm-ir` dependency to 0.7.1 (from 0.6.0), which includes runtime
and memory-usage performance improvements, particularly for large bitcode
files. This also involves a few breaking changes to parts of `haybale`'s API.
- `haybale` now requires Rust 1.43+ (previously 1.40+) due to requirements
of `llvm-ir` 0.7.1.

### Version 0.5.1 (Aug 31, 2020)

- Fix for [issue #9]https://github.com/PLSysSec/haybale/issues/9 regarding
zero-element arrays (which particularly may appear when analyzing Rust code)
- Built-in support for the `llvm.ctlz` and `llvm.cttz` intrinsics

### Version 0.5.0 (Jul 29, 2020)

Compatibility:
- `haybale` now depends on LLVM 10 by default (up from LLVM 9). LLVM 9 is
still supported on a separate branch; see "Compatibility" above.
- Updated `boolector` dependency to crate version 0.4.0, which requires
Boolector version 3.2.1 (up from 3.1.0).

Renames which affect the public API:
- Rename `SimpleMemoryBackend` to `DefaultBackend` and make it default.
Rename `BtorBackend` to `CellMemoryBackend`, and the `memory` module to
`cell_memory`.
- Remove the `layout` module. Its functions are now available as methods on
[`State`]. Also, many of these functions now return `u32` instead of `usize`.

32-bit targets and related changes:
- With `DefaultBackend`, `haybale` now supports LLVM bitcode which was
compiled for 32-bit targets (previously only supported 64-bit targets).
- The [`new_uninitialized()`] and [`new_zero_initialized()`] methods on the
[`backend::Memory`] trait, `simple_memory::Memory`, and `cell_memory::Memory`
now take an additional parameter indicating the pointer size.
- `Project` has a new public method [`pointer_size_bits()`].

Other:
- Built-in support for the `llvm.expect` intrinsic, and built-in support for
the `llvm.bswap` intrinsic with vector operands (previously only supported
scalar operands)
- [`solver_utils::PossibleSolutions`] has new constructors `empty()`,
`exactly_one()`, and `exactly_two()` (useful for testing), and also
implements `FromIterator`, allowing you to `.collect()` an iterator into it
- Bugfix for the `{min,max}_possible_solution_for_bv_as_binary_str()`
functions in the `solver_utils` module

### Version 0.4.0 (Mar 31, 2020)

New features:
- Support LLVM `cmpxchg` instructions
- Support for instruction callbacks - see [`Config.callbacks`]. This allows
you to take arbitrary actions based on the instruction about to be processed.

Config:
- `Config.null_detection` has been renamed to
[`Config.null_pointer_checking`], and its type has been changed to allow for
additional options.
- `Config::new()` now takes no parameters. It is now the same as
`Config::default()` except that it comes with no function hooks.

Other utility functions/methods:
- The `hook_utils` module now includes two new functions [`memset_bv`] and
[`memcpy_bv`].
- [`layout::size_opaque_aware`] now returns an `Option` rather than panicking.
- The `to_string_*` methods on [`Location`] are now public, rather than
internal to the crate, allowing users more control over the `String`
representation of a `Location`.

Error handling:
- [`Error`] has three new variants `UnreachableInstruction`,
`FailedToResolveFunctionPointer`, and `HookReturnValueMismatch`. All of these
were previously reported as `Error::OtherError`, but now have dedicated
variants.
- `Error::LoopBoundExceeded` now also includes the value of the loop bound
which was exceeded.

Other notes:
- `haybale` no longer selects features of the `log` crate. This allows
downstream users to select these features or not, and in particular, allows
users to enable debug logging in release builds.

### Version 0.3.2 (Feb 28, 2020)

- New option [`Config.max_callstack_depth`] allows you to limit the callstack
depth for an analysis - automatically ignoring calls of LLVM functions which
would exceed that callstack depth. The default for this setting is no limit,
matching the previous behavior of `haybale`.
- New option [`Config.max_memcpy_length`] allows you to limit the maximum
size of `memcpy`, `memset`, and `memmove` operations. The default for this
setting is no limit, matching the previous behavior of `haybale`.
- New method [`FunctionHooks::add_default_hook()`] allows you to supply a
"default hook" which will be used when no other definition or hook is found
for a function call. If no default hook is provided, this will result in a
`FunctionNotFound` error, just as it did previously.
- Performance improvements for analyzing calls of function pointers.
- Improved a few error messages.

### Version 0.3.1 (Feb 5, 2020)

- Fix some broken links in the README and docs. No functional changes.

### Version 0.3.0 (Feb 5, 2020)

Solver timeouts:
- New setting [`Config.solver_query_timeout`] controls the maximum amount of
time `haybale` will spend on a single solver query before returning
`Error::SolverError`. This setting defaults to 300 seconds (5 minutes).
The setting can also be disabled entirely, which results in the same behavior
as previous versions of `haybale` (no time limit on solver queries).

Error handling:
- The errors returned by `ExecutionManager.next()` are now `haybale::Error`s
instead of `String`s, allowing callers to more easily handle different kinds
of errors different ways. To get a string representation of the `Error`,
`.to_string()` gives the short description, while
[`State.full_error_message_with_context()`] gives the full description which
previously was returned by `ExecutionManager.next()`. The usage example in
the README has been updated accordingly.
- The toplevel function [`find_zero_of_func()`] now returns a
`Result`, with the error type being `String`.
- New setting [`Config.squash_unsats`] controls whether `Error::Unsat`s are
silently squashed (the default behavior, and the behavior of previous
versions of `haybale`), or returned to the user. For more details, see the
docs on that setting.

Logging, error messages, backtraces, etc:
- `haybale` now prints source-location information (e.g., source filename and
line number) in error messages and backtraces when it is available.
Similarly, the `HAYBALE_DUMP_PATH` environment variable now has the options
`LLVM`, `SRC`, and `BOTH`. For more details on all of this, see
[`Config.print_source_info`].
- You can also now _disable_ printing the LLVM module name along with LLVM
location info in error messages, backtraces, path dumps, and log messages.
For more details, see [`Config.print_module_name`].
- `haybale` will now by default autodetect when C++ or Rust demangling is
appropriate for the `Project`, unless a different setting is chosen in
[`Config.demangling`].
- Numeric constants representing `BV` values in log messages,
`HAYBALE_DUMP_VARS` dumps, etc are now all printed in hexadecimal (previously
binary, or an inconsistent mix of binary and hexadecimal).

Function hooks and intrinsics:
- Built-in support for LLVM arithmetic-with-overflow intrinsics.
- Built-in support for LLVM saturating-arithmetic intrinsics.
- Built-in support for the `llvm.assume` intrinsic, with an associated
setting [`Config.trust_llvm_assumes`].
- Built-in support for the `llvm.bswap` intrinsic with argument sizes 48
or 64 bits (previously only supported 16 or 32 bits).
- Default hooks for a number of Rust standard-library functions which
always panic, such as `core::result::unwrap_failed()`.
- New module `hook_utils` contains the implementations of `memset` and
`memcpy` used by the corresponding built-in hooks. These are now publically
available for use in custom hooks for other functions.

Changes to data structures and traits:
- The `Location` and `PathEntry` structs have been refactored to include
source-location information when it is available, to be capable of indicating
basic block terminators in addition to normal instructions, and to support
some internal refactoring.
- The [`backend::BV`] trait has a new required method, `get_solver()`, which
returns a `SolverRef` of the appropriate type. (This is similar to the same
method on the `backend::Memory` trait.)
- Saturating-arithmetic methods (signed and unsigned addition and subtraction)
are now available on [`backend::BV`], with default implementations in terms
of the other trait methods. That means that these come "for free" once the
required trait methods are implemented.
- `zero_extend_to_bits()` and `sign_extend_to_bits()` are also now available
as trait methods on [`backend::BV`], with default implementations in terms of
the other trait methods. Previously they were private utility functions in
`haybale`.
- Many other structures have had minor changes and improvements, including
some small breaking changes.

Compatibility:
- Updated `boolector` dependency to crate version 0.3.0, which requires
Boolector version 3.1.0 (up from 3.0.0).
- This version of `haybale` now requires Rust 1.40+, up from 1.36+ for
previous versions of `haybale`.

### Version 0.2.1 (Jan 15, 2020)

- New `HAYBALE_DUMP_PATH` and `HAYBALE_DUMP_VARS` environment-variable options
  - `HAYBALE_DUMP_PATH`: if set to `1`, then on error, `haybale` will print a
  description of the path to the error: every LLVM basic block touched from
  the top of the function until the error location, in order.
  - `HAYBALE_DUMP_VARS`: if set to `1`, then on error, `haybale` will print the
  latest value assigned to each variable in the function containing the error.
- New setting `Config.demangling` allows you to apply C++ or Rust demangling
to function names in error messages and backtraces
- Support hooking calls to inline assembly, with some limitations inherited
from [`llvm-ir`] see comments on [`FunctionHooks::add_inline_asm_hook(`])
- Built-in support for (the most common cases of) the `llvm.bswap` intrinsic
- Other tiny tweaks - e.g., downgrade one panic to a warning

### Version 0.2.0 (Jan 8, 2020)

- Support LLVM `extractvalue` and `insertvalue` instructions
- Support LLVM `invoke`, `resume`, and `landingpad` instructions, and thus
C++ `throw`/`catch`. Also provide built-in hooks for some related C++ ABI
functions such as `__cxa_throw()`. This support isn't perfect, particularly
surrounding the matching of catch blocks to exceptions: `haybale` may explore
some additional paths which aren't actually valid. But all actually valid
paths should be found and explored correctly.
- Since functions can be called not only with the LLVM `call` instruction but
also with the LLVM `invoke` instruction, function hooks now receive a
`&dyn IsCall` object which may represent either a `call` or `invoke` instruction.
- `haybale` now uses LLVM 9 rather than LLVM 8. See the "Compatibility"
section in the README.
- Improvements for `Project`s containing C++ and/or Rust code:
  - For the function-name arguments to [`symex_function()`],
    [`get_possible_return_values_of_func()`], [`find_zero_of_func()`], and
    [`Project::get_func_by_name()`], you may now pass either the (mangled)
    function name as it appears in LLVM (as was supported previously), or the
    demangled function name. That is, you can pass in `"foo::bar"` rather than
    `"_ZN3foo3barE"`.
  - Likewise, you may add function hooks based on the demangled name of
    the hooked function. See [`FunctionHooks::add_cpp_demangled()`] and
    [`FunctionHooks::add_rust_demangled()`].
  - Also, `llvm-ir` versions 0.3.3 and later contain an important bugfix for
    parsing LLVM bitcode generated by `rustc`. `haybale` 0.2.0 uses `llvm-ir`
    0.4.1.
- The [`ReturnValue`] enum now has additional options `Throw`, indicating an
uncaught exception, and `Abort`, indicating a program abort (e.g. Rust
panic, or call to C `exit()`).
- Relatedly, `haybale` now has built-in hooks for the C `exit()` function and
for Rust panics (and for a few more LLVM intrinsics).
- `haybale` also now contains a built-in [`generic_stub_hook`] and
[`abort_hook`] which you can supply as hooks for any functions which you want
to ignore the implementation of, or which always abort, respectively. See
docs on the [`function_hooks`] module.
- [`Config.initial_mem_watchpoints`] is now a `HashMap` instead of a `HashSet`
of pairs.

### Version 0.1.3 (Jan 1, 2020)

- Memory watchpoints: specify a range of memory addresses, and get
a log message for any memory operation which reads or writes any data in
that range. See [`State::add_mem_watchpoint()`].
- Convenience methods on [`State`] for constructing constant-valued `BV`s
(rather than having to use the corresponding methods on `BV` and pass
`state.solver`): `bv_from_i32()`, `bv_from_u32()`, `bv_from_i64()`,
`bv_from_u64()`, `bv_from_bool()`, `zero()`, `one()`, and `ones()`.
- Some internal code refactoring to prepare for 0.2.0 features

### Version 0.1.2 (Dec 18, 2019)

- New method [`Project::get_inner_struct_type_from_named()`] which handles
opaque struct types by searching the entire `Project` for a definition of
the given struct
- Support memory reads of size 1-7 bits (in particular, reads of LLVM `i1`)
- Performance optimization: during `State` initialization, global variables
are now only allocated, and not initialized until first use (lazy
initialization). This gives the SMT solver fewer memory writes to think
about, and helps especially for large `Project`s which may contain many
global variables that won't actually be used in a given analysis.
- Minor bugfixes and improved error messages

### Version 0.1.1 (Nov 26, 2019)

Changes to README text only; no functional changes.

### Version 0.1.0 (Nov 25, 2019)

Initial release!

[`llvm-ir`]: https://crates.io/crates/llvm-ir
[Boolector]: https://boolector.github.io/
[`boolector`]: https://crates.io/crates/boolector
[`llvm-sys`]: https://crates.io/crates/llvm-sys
[KLEE]: https://klee.github.io/
[`Project`]: https://docs.rs/haybale/latest/haybale/project/struct.Project.html
[`Project` documentation]: https://docs.rs/haybale/latest/haybale/project/struct.Project.html
[`Project::get_func_by_name()`]: https://docs.rs/haybale/latest/haybale/project/struct.Project.html#method.get_func_by_name
[`get_possible_return_values_of_func()`]: https://docs.rs/haybale/latest/haybale/fn.get_possible_return_values_of_func.html
[`find_zero_of_func()`]: https://docs.rs/haybale/latest/haybale/fn.find_zero_of_func.html
[`ExecutionManager`]: https://docs.rs/haybale/latest/haybale/struct.ExecutionManager.html
[`ExecutionManager` documentation]: https://docs.rs/haybale/latest/haybale/struct.ExecutionManager.html
[`symex_function()`]: https://docs.rs/haybale/latest/haybale/fn.symex_function.html
[`get_path_length()`]: https://docs.rs/haybale/latest/haybale/fn.get_path_length.html
[`Config`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html
[`BV`]: https://docs.rs/boolector/0.4.2/boolector/struct.BV.html
[`ReturnValue`]: https://docs.rs/haybale/latestt/haybale/enum.ReturnValue.html
[`Error`]: https://docs.rs/haybale/latest/haybale/enum.Error.html
[`State`]: https://docs.rs/haybale/latest/haybale/struct.State.html
[`Location`]: https://docs.rs/haybale/latest/haybale/struct.Location.html
[`Project::get_inner_struct_type_from_named()`]: https://docs.rs/haybale/latest/haybale/struct.Project.html#method.get_inner_struct_type_from_named
[`State::add_mem_watchpoint()`]: https://docs.rs/haybale/latest/haybale/struct.State.html#method.add_mem_watchpoint
[`FunctionHooks::add_cpp_demangled()`]: https://docs.rs/haybale/latest/haybale/function_hooks/struct.FunctionHooks.html#method.add_cpp_demangled
[`FunctionHooks::add_rust_demangled()`]: https://docs.rs/haybale/latest/haybale/function_hooks/struct.FunctionHooks.html#method.add_rust_demangled
[`FunctionHooks::add_inline_asm_hook()`]: https://docs.rs/haybale/latest/haybale/function_hooks/struct.FunctionHooks.html#method.add_inline_asm_hook
[`FunctionHooks::add_default_hook()`]: https://docs.rs/haybale/latest/haybale/function_hooks/struct.FunctionHooks.html#method.add_default_hook
[`function_hooks`]: https://docs.rs/haybale/latest/haybale/function_hooks/index.html
[`generic_stub_hook`]: https://docs.rs/haybale/latest/haybale/function_hooks/fn.generic_stub_hook.html
[`abort_hook`]: https://docs.rs/haybale/latest/haybale/function_hooks/fn.abort_hook.html
[`Config.initial_mem_watchpoints`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.initial_mem_watchpoints
[`Config.demangling`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.demangling
[`Config.print_source_info`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.print_source_info
[`Config.print_module_name`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.print_module_name
[`Config.trust_llvm_assumes`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.trust_llvm_assumes
[`Config.solver_query_timeout`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.solver_query_timeout
[`Config.squash_unsats`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.squash_unsats
[`Config.max_callstack_depth`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.max_callstack_depth
[`Config.max_memcpy_length`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.max_memcpy_length
[`Config.callbacks`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.callbacks
[`Config.null_pointer_checking`]: https://docs.rs/haybale/latest/haybale/config/struct.Config.html#structfield.null_pointer_checking
[`backend::BV`]: https://docs.rs/haybale/latest/haybale/backend/trait.BV.html
[`backend::Memory`]: https://docs.rs/haybale/latest/haybale/backend/trait.Memory.html
[`new_uninitialized()`]: https://docs.rs/haybale/latest/haybale/backend/trait.Memory.html#tymethod.new_uninitialized
[`new_zero_initialized()`]: https://docs.rs/haybale/latest/haybale/backend/trait.Memory.html#tymethod.new_zero_initialized
[`State.full_error_message_with_context()`]: https://docs.rs/haybale/latest/haybale/struct.State.html#method.full_error_message_with_context
[`memcpy_bv`]: https://docs.rs/haybale/latest/haybale/hook_utils/fn.memcpy_bv.html
[`memset_bv`]: https://docs.rs/haybale/latest/haybale/hook_utils/fn.memset_bv.html
[`layout::size_opaque_aware`]: https://docs.rs/haybale/latest/haybale/struct.State.html#method.size_opaque_aware
[`pointer_size_bits()`]: https://docs.rs/haybale/latest/haybale/struct.Project.html#method.pointer_size_bits
[`solver_utils::PossibleSolutions`]: https://docs.rs/haybale/latest/haybale/solver_utils/enum.PossibleSolutions.html
[`get_bv_by_irname()`]: https://docs.rs/haybale/latest/haybale/struct.State.html#method.get_bv_by_irname