When translation of code overflows into an unmapped page, we can get a
SIGSEGV. To avoid this, for each set of contiguous pages, we add "guard
page" containing an architecture-specific pattern that ensure basic
block termination.
Unlike the previous iteration of `MetaAddress`, which tried to stuff all
the parts of `MetaAddress` within the existing `PC` CSV, this
implementation adds a set of new CSVs (or marks some existing ones as) to
represent the four portions of the current PC's `MetaAddress`.
* Introduce `ProgramCounterHandler`: a class responsible to maintain the
PC-related CSVs. This class is also used to manipulate the new
dispatcher.
* `AdvancedValueInfo`: update for new MetaAddress.
* External jump handler: do not clobber registers.
When introducing support for dynamic binaries, we didn't realize that
in x86-64 we were clobbering `r11`. To avoid this, we have to jump to
an address stored in memory. However, due to the new `MetaAddress`,
obtaining a *jumpable* address from the PC-related CSVs might require
some computations (and it does in ARM). Therefore, we introduce a new
global variable, `jumpablepc`, whose only role is to contain the
jumpable version of the program counter and then be the target of the
memory-indirect jump instruction.
* Labels care only about absolute addresses.
* CSAA: mark call site, even if no accesses.
`MetaAddress` replaces all the `uint64_t` used to represent a virtual
address. Its main features are:
* It has a non-zero representation of invalid addresses.
* It supports tags to represent code that has different interpretations but
resides at the same address in memory (namely ARM vs Thumb).
* Arithmetic operations cannot overflow.
* It supports epochs, a way we intend to employ to handle self-modifying code
(i.e., different code at the same address at different times).
* It supports "address spaces", which enable handling architectures with
multiple address spaces.
* It fits in two 64-bit registers.
* Drop unused argument names from function prototypes
* Make `static` some methods
* Disable some copy constructors
* Fix casing of Doxygen `\file` directives
* Add some casts to make the compiler happy
* Initialize `hasRelocationAddend` for AArch64
* Use references in range-for where possible
* Drop default for `switch` statements covering all the entries of an `enum`
* Make some global variables `static`
* Drop dead functions
LLVM already implements an analogous `mapped_iterator` type in
`STLExtras.h` header. `llvm::mapped_iterator` has been used to
substitute `TransformIterator` in the project so that we don't need to
reinvent the wheel.
Before this commit, the `dumpToString()` function defined in
`include/revng/Support/IRHelpers.h` was only defined with arguments of
type `const llvm::Module *` and `const llvm::Value *`.
This is not very ergonomic, because lots of types in LLVM have a
`print()` method that dumps the representation on a
`llvm::raw_ostream``.
This commit introduces function templates to handle all possible types
in LLVM that have a method `void print(llvm::raw_ostream &)`.
The templates are defined so that they should work with every possible
combination of references and pointer types, along with const
qualifiers.
To achieve this, the code makes use of `std::enable_if`` to provide
different definitions of the `dumpToString()` template helper function,
which only participate in overload resolution for specific types:
1. for `llvm::Module` and `llvm::Function`, which share the same
prototype for the `print()` method
2. for `llvm::Value` which has yet another prototype for the `print()`
method
3. for all other types that provide a method with the signature
`void print(llvm::raw_ostream &)`.
The last implementation (3) also works for all non-LLVM types provide a
method with the signature `void print(llvm::raw_ostream &)`.
In this sense, if in the future we want our own type to be easily dumped
to string (handy for logging), we can just implement the method
`void print(llvm::raw_ostream &)` and the `dumpToString()` function
template added in this commit will work out ot the box.
Handle `ConstantPointerNull` explicitly in Advanced Value Info, instead
of trying to obtain the analysis result for its operand (which is by
design a `nullptr`).
Before this commit, the header `revng/Support/DebugHelper.h` could only
be included after explicitly including
`llvm/IR/AssemblyAnnotationWriter.h`, since `DebugHelper.h` used the
LLVM class `AssemblyAnnotationWriter`, that is not defined in
`DebugHelper.h`.
This commit includes `llvm/IR/AssemblyAnnotationWriter.h` directly into
`revng/Support/DebugHelper.h`, which can now be included alone without
compilation errors.
A `ConstantRange` such as `[5,0)` was not handled correctly in
`ConstantRangeSet` due to a spurious 0 at the end of the range.
This commit also fixes the testing infrastructure that was not checking
the size of the range before making the comparison with the reference
vector.
LLVM 9 drops the `TerminatorInst` class. This commit replaces it with
`Instruction` where possible and asserts
`Instruction::isTerminator()`. It also switches from
`TerminatorInst::successors` to `successors(TerminatorInst *)`.
This commit restores the old implementation of `getBasicBlockPC` (which
was changed in an incompatible and wrong way) and fixes the bug the
original change tried to fix: in function isolation, jumping from a
function to a basic block that doesn't start with `newpc` now leads to a
basic block containing an `unreachable`.
* Introduce `ShrinkInstructionOperandsPass`: a transformation shrinking
operands and the results of instructions if they are
zero/sign-extended immediately before and after the instruction.
* Introduce `ConstantRangeSet`: similar to `ConstantRange` but allows
disjoint ranges.
* Introduce `MaterializedValue`: a class that can represent a constant
value or a symbol plus offset pair.
* Introduce `DropHelperCallsPass`: a transformation removing calls to
helpers and replacing them with a function call reading the CSVs that
the helper reads and writing the CSVs that the helper writes
(according to CSAA).
* Introduce `DropRangeMetadataPass`: a transformation dropping the
`range` metadata, which, in certain situations, lowers the quality of
the results provided by `LazyValueInfo`.
* Introduce `AdvancedValueInfo`: an analysis exploiting results of
`LazyValueInfo` but collecting them as `ConstantRangeSet` with a
monotone framework. It produces `MaterializedValue`.
* Anticipate linking of helpers: `AVI` requires `CSAA`, which requires
helper functions to be linked in.
* Drop `--no-link`.
* Force x86-64 `DataLayout`.
* Reorganize harvesting to either collect simple literals or go with
(incremental) `AVI`.
* Drop `SET`, `OSRA`, the reaching definition analysis, the
`SimplifyComparisonsPass` and all the sumjump-related code: e now
clone `root`, optimize it and analyze it with `AVI`.
* Temporarily drop the `NoReturnAnalysis`.
* Link `libLLVMInstCombine`, `libLLVMCodeGen` and `libLLVMPasses`.
* Introduce tests for `AdvancedValueInfo`,
`ShrinkInstructionOperandsPass` and `ConstantRangeSet`.
* Fix test results.
* Add `llvm.bswap.i64` and `@pc` to the LLVM template module for unit
tests.
Any stack pointer value greater than or equal to the original one used
to be OK for stack analysis to recognize an instruction as a
return. This commit changes this policy by collecting the value of the
stack pointer on all the return points and, at the end, elect a final
stack pointer value. All non-compliant returns are marked a
`BranchType::BrokenReturn`. The function is now considered fake only if
all the return instructions agree on a specific value of the stack
pointer, and it's lower than the original one.
* Drop `BranchType::IndirectTail`.
* `s/BranchType::FunctionSummary/BranchType::RegularFunction/`.
A series of algorithms working on `llvm::GraphTraits`.
* `nodesBetween` computes the set of nodes on all the paths from a node
A to B.
* Factor out code to iterate over infinite loops into
`exitless_scc_range`.
* Introduce unit tests.
Let the user provide the list of the basic blocks to visit, in a
specific order. This is useful when the same graph has to be visited
multiple times to avoid having `MonotoneFramework` recompute the reverse
post order each time.
* Introduce `KeyContainer::compare` and drop the `getKey` method.
* Let users of ZipMapIterator specify a trait class instead of using the
default one.
* `GeneratedCodeBasicInfo::getCSVUsedByHelperCall` and
`GeneratedCodeBasicInfo::extractCSVs`: make the call argument an
`Instruction`.
* Introduce `blockByName`
* Introduce `getUniqueUser`.
* Fix linking issues.
This commit enlarges the set of external function calls we
detect. Basically, instead of assuming that the instruction jumping to
the external function is the call, we now also consider instructions in
previous basic blocks, as long as there's only one possible path
backward.
In certain locations we were using a `std::vector`, taking a reference
to it, adding elements and ending up in a reference invalidation issue.
This commit replaces those `std::vectors` with `std::deque` which do not
present this issue.
This commit introduces the `enforce-abi` pass, which consumes the
information provided by the ABI analysis and enforces them in the
isolated functions adding actual arguments.
This commit also rewrites the logic of `ResultsPool::finalize` and
changes the semantic of `Yes` statements on arguments to `YesOrDead`.
`empty-newpc` is a simple pass suppose to provide an empty body for
the `newpc` function, allowing further optimization pass to take out
all its calls.
`ZipMapIterator` allows you to iterate in parallel over two
`std::map`-like containers.
In the ABI analysis, this allows us to be much more efficient. In
practice, if we have two maps with M and N elements, we pass from
performing N*log(N) + M*log(M) queries to the size of the union of the
set of keys of the two maps.