Files
2over12 eef338df00 Ian/sleigh support rebased (#607)
* cmake: Bring in SLEIGH as a dependency

* sleigh: Boilerplate for adding a new arch

* sleigh: Begin passing instruction sequences into SLEIGH

* cmake: Rename target to be X86 specific

* sleigh: Copy over more X86 runtime code and get things running

* sleigh: Begin populating operands in the returned instruction

* sleigh: Set instruction category for a few opcodes

* sleigh: Initial attempt at generating LLVM IR for P-Code

* sleigh: Implement enough opcodes to run the `sleigh-lift` example

* sleigh: Get things building with an up-to-date Remill tree

* sleigh: Use the new SLA helpers

* sleigh: Clear operands between invalid lifts

* added thumb2

* stub out thumb

* need to refactor to relift the instruction

* factored lifter out of handler:

* allow lifters to decide wether to use sleigh

* relift bytes

* fixed both lifter contexts

* hey a copy lifted :)

* need to refactor to use parameterptrs to unify interface to memory

* refactored to use parameter abstraction

* lift at correct location

* add control flow to pc and next

* add categories mostly

* fix direct semantics add cbranch

* track cbranch metavar also lift returns

* cmake: Fix SleighArch.h path

* sleigh: Support more binary ops

* sleigh: Implement ZEXT

* sleigh: Support SEXT op

* sleigh: Implement 2COMP and INT_NEGATE

* mutex around parsing sleigh specs

* fixed typos in custom image

* added handling for exceptions, need to fix issue with xml parsing

* sleigh: Support boolean binops

* sleigh: Support float binary ops

* sleigh: Support a few more float pcode ops that require LLVM intrinsics

* sleigh: Add entries for ops that require overflow intrinsics

* sleigh: Implement more float unary ops

* sleigh: Reduce duplication in ops that require float intrinsics

* expose mutex

* fix fallthough and format of control flow resolution

* sleigh: Support CARRY, SCARRY and SBORROW

* Remove duplicate THUMB2 arch in enum

* Remove duplicate THUMB2 entry in archnames array

* Implement STORE op

* Fix incorrect index

* Support PIECE and SUBPIECE ops

* Support remaining set of PCode ops in the base set. Now to do the
pseudo ops.

* Implement additional ops

* Partially implement a few pseudo ops + a few missing from the docs

* Fix the variadic op condition

* Include <mutex> to build on Linux

* stop lying about insn categories/functions

* set function insns with mnemonic

* fix fallthrough for ind calls

* More virtualization, fewer pimples

* switch back to x86 normal

* Fix off-by-eight issue with ADR in AArch32

* Get rid of mutex in sleigh, make a globally-available remill locker for handling sleigh issues

* CHange allow 32 bit shift to true, not sure if valid but oh well

* Use the node size when creating constants

* fix memory

* store memory state back

* fix calling intrinsic table

* fix comp sizes

* load pspec data

* add pspec names

* add differential test

* fix tests start pretty printer

* add runner

* added really slow memory

* add comparison of memory state

* do reset

* fix uninitialized module

* fixed lift crash

* add amd64 runtime

* unfix fs, gs, and pc

* added whitelist file

* fix memory to update state with uninitialized reads

* better pc handling

* add main.py

* x86 compiles

* fixup patch generation

* add replacements for mem locs and constant varnodes, now need to handle special branches

* added replacement for direct branches

* add context clears

* add handler for claim_eq

* comment out clears for now

* added ambiguity check

* handle duplicate names in same constructor

* mantain sleigh invariant of 1 or 0 in flag

* added uint8t memory intrinsics

* extend shift value when needed

* handle cmovs

* update patch generation

* removed deprecated load

* fix for returned type

* builds

* add logging

* add comment on why not compute GEPAccessors in Arch.cpp

* enable opaque pointers

* fix memory state update

* add mem_16 impls

* not preserve 1 bit width

* fix CR changes

* fix L and R for shift operands bigger than target

* revert use after move

* more CR fixes

* remove lookahead... lets try this again

* rework to create internal function that is inlined to allow for early return control flow

* terminate conditionally

* avoid large iteration counts for .REP insns

* fix patch for rep insns

* handle inst_start in patches

* handle inserting insn_size constructor outside of macros

* hint size of insn_size

* refactor bool functions to make more sense

* just use ;

* remove delete of operands when fail to lift

* remove copy and paste

* remove unused deps

* add patch file to sleigh list

* prep git user

* refer to checkout

* maybe shell type?

* fix layout

* fix format again

* fix

* update dockerfile

* fix gitwatcher to point to current project:

* Revert "fix gitwatcher to point to current project:"

This reverts commit 711da11e6f.

* fix ninja builds

* disable sleigh tests

* remove duplicates

* refactor

* fix non reset context in sleigh lifter

* remove debugging prints

* wrote CI runner

* add handwritten test infra

* refactor to allow sharing JIT test running between differential tester and hand written tests

* allow for internal ownership of semantics module

* handwritten test framework

* fix hand written tests

* pc rel testruns

* add pc rel regression

* fix script for pc rel

* fix names for priors to ignore whitespace

* fix action ops

* add xor to repl ops

* add xors to patch

* add arm patch to build

* fix test for semantics

* allow cross platform tests to run

* add running diff tester

* 2 underscores?

* run tests on macos too

* fix command

* fix whitelist path

* remove unused test data

* install python deps for differential tests

* update script to git patches

* update patches to git format

* attempt to fixup patches

* update ref for sleigh

* install test depends docker

* point docker to correct dir

* install pydeps in macos too

* initialize address field

* exports, also tag master on sleigh

* add comments and whitelist undefined value OF in shifts

* add of accessor to whitelist impl

* change variables to non alloca and remove dead code

* remove dead code:

* replace dump with print

* code quality

* make non null into ref

* type alias

* remove allocas from unit tests

* Address copypasta comment.

* Address PR comment.

* Address PR comment.

* fix build

* unify diff modules into single structure

* remove extra newline

* lock sleigh to specific commit

* remove new lines

* remove useless fenv headers

* caps

* copyright notices

* update more copyright

* fix reviews

* early returns out of accessors

* early return

* auto

* return getarchbyname

* insert register rather than modify reference

* just return

* only log in the assembly logger

* prefer functional style

* remove commented code

* move defaults to header

* that's not how arch switches work in pcode

* informative names

* simplify control flow in fill

* early return

* fix early exit condition

* refactor register default into function

* make one liner

* early return

* unary instead of unop

* construct pair with {}

* move cbranch into binops instead of integer binops

* refactor float ops into getter

* factor out float type

* early return

* separate out callother handling

* do pointer extensions cleaner

* braces

* add private headers to lifters

* refactor redirecting control flow out of instruction

* use constant check function

* remove has_value

* structure for preconditions

* return success when applying eq claim

* expose arch base and move shared functionality into x86 base

* dedup x86 code

* dedup aarch32

* remove needless assignment, also remove else after an if that returns

Co-authored-by: Alex Cameron <asc@tetsuo.sh>
Co-authored-by: Artem Dinaburg <artem@trailofbits.com>
Co-authored-by: Peter Goodman <peter.goodman@gmail.com>
2022-07-28 08:46:32 -04:00

163 lines
4.4 KiB
C++

/*
* Copyright (c) 2022 Trail of Bits, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Whitelist.h"
#include <glog/logging.h>
#include <llvm/Support/JSON.h>
#include <string>
#include <string_view>
#include <unordered_map>
namespace {
const static std::unordered_map<
std::string, std::function<void(X86State *, std::string_view)>>
accessors = {
{"gpr",
[](X86State *state, std::string_view target) {
uint32_t *target_ptr =
[state](std::string_view target) -> uint32_t * {
if (target == "rip") {
return &state->gpr.rip.dword;
}
if (target == "rax") {
return &state->gpr.rax.dword;
}
return nullptr;
}(target);
if (!target_ptr) {
std::string s(target);
throw std::runtime_error(std::string("Unknown reg: ") + s);
}
*target_ptr = 0;
}},
{"aflags", [](X86State *state, std::string_view target) {
uint8_t *target_ptr = [state](std::string_view target) -> uint8_t * {
if (target == "af") {
return &state->aflag.af;
}
if (target == "zf") {
return &state->aflag.zf;
}
if (target == "of") {
return &state->aflag.of;
}
return nullptr;
}(target);
if (!target_ptr) {
std::string s(target);
throw std::runtime_error(std::string("Unknown reg: ") + s);
}
*target_ptr = 0;
}}};
}
void Accessor::ApplyOverride(X86State *state) const {
if (accessors.find(this->section) == accessors.end()) {
throw std::runtime_error(std::string("Couldnt find section ") +
std::string(this->section));
}
accessors.find(this->section)->second(state, this->target_name);
}
bool Accessor::fromJSON(const llvm::json::Value &E, llvm::json::Path P) {
std::vector<std::string> section_names;
if (!llvm::json::fromJSON(E, section_names, P.field("state_target"))) {
return false;
}
if (section_names.size() != 2) {
P.field("state_target")
.report(
"Currently only supports access paths of the form [section, target_var]");
return false;
}
this->section = section_names[0];
LOG(INFO) << "Section is: " << this->section;
this->target_name = section_names[1];
return true;
}
bool WhiteListInstruction::fromJSON(const llvm::json::Value &E,
llvm::json::Path P) {
auto maybe_obj = E.getAsObject();
if (!maybe_obj) {
P.report("Should be an object");
return false;
}
auto maybe_isel_name = maybe_obj->find("isel_name");
if (maybe_isel_name == maybe_obj->end()) {
P.report("Should have isel_name object");
return false;
}
std::string isel_name = "";
if (!llvm::json::fromJSON(maybe_isel_name->second, isel_name,
P.field("isel_name"))) {
return false;
}
auto maybe_state_target = maybe_obj->find("state_target");
if (maybe_state_target == maybe_obj->end()) {
P.report("Should have state target path");
return false;
}
if (!llvm::json::fromJSON(maybe_state_target->second,
this->target_state_portion,
P.field("state_target"))) {
return false;
}
this->target_isel_prefix = isel_name;
return true;
}
void WhiteListInstruction::ApplyToInsn(std::string_view isel_name,
X86State *state) const {
if (isel_name.rfind(target_isel_prefix, 0) == 0) {
this->target_state_portion.ApplyOverride(state);
}
}
namespace llvm::json {
bool fromJSON(const Value &E, Accessor &Out, Path P) {
return Out.fromJSON(E, P);
}
bool fromJSON(const Value &E, WhiteListInstruction &Out, Path P) {
return Out.fromJSON(E, P);
}
} // namespace llvm::json