mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
e1bdbdba9e
* Change copyright notice in all the places. Trying to get cmake to download all the things * CMake refactor * Added the lib repository installer * Fixed a couple of paths in library repository scripts * Spelling and a missing .gitignore file. * The google test library was not correctly linked * Removed the pre-compiled XED library * Removed unused files; fixed the INSTALL directives. Added automatic protobuf generation. * Added a package generator script for ArchLinux * Merged in Alessandro's cmake magic * Cleanups, compatibility changes * CMake cleanup. o Removed the cmake folder as it is no longer used. o Removed the library_repository_installer directory and replaced it with a submodule to the newly introduced cxx_common repository. o Added the 'use_remill_semantics' branch of mcsema as a submodule under tools/cmake. o Updated the README instructions (added --recursive to the git clone command). Warning: the mcsema submodule is pointing to my fork of the repository! * CMake: avoid re-defining the C/CXX/ASM compiler. This will prevent CMake from looping forever when using submodules. * The tools/mcsema submodule now points to the official repository. * mcsema submodule update * Updated the mcsema git submodule to track the newest changes. * Various CMake fixes (see details). o External include headers were not correctly marked as SYSTEM. This caused them to output warnings and break the build. o The PROJECT_SOURCE CMake variable has been replaced with CMAKE_SOURCE_DIR. o Updated the mcsema submodule to point to the latest CMake fixes. * Getting closer to having the test case runner work again without using the CFG protobufs. * Trying to make things use ubuntu clang/llvm packages * Update to the mcsema submodule. * Minor changes for llvm version compatibility * Test cases should run now. Had to compile the lifted testcases to a .S file, as with the .bc file, they were being optimized away.. I think. The compilation to assembly seems unusually slow, though. * Minor change * Some stuff for llvm 4.0 support * Remove mcsema sub-module * Remove cxx-common submodule * First steps toward getting travis working again * Attempt at getting travis working again * Using https for cloning instead of ssh * Minor build script update * Added ISEL_ prefix to isels to make it easier for ForEachISel to find them. Commented out the defer_inlining intrinsics. * Changes related to mcsema2 * Simplify runtime targets generation. (#110) * CMake refactor: Added a new language 'BC' for the bitcode (see details). The language is used to generate the runtimes used by the architecture modules. The required executables (clang++ and llvm-link) are automatically detected in the same way as other compilers are. A new CMake function has been added and it can be used to easily generate runtime targets in a way similar to add_executable: add_runtime(<name> SOURCE <source list> ADDRESS_SIZE <n> DEFINITIONS <definition list>) Additionally, all files ending with the *.bcpp extensions will automatically invoke the bitcode compiler when listed in an active target. This should open support for parallel compilation! You just have to list all your .cpp files when calling add_runtime. * CMake: Fixes to the BC language handler. * CMake/BC: Use '.bo' for object files. X86 runtime: Add -g/-O flags.
186 lines
5.2 KiB
C++
186 lines
5.2 KiB
C++
/*
|
|
* Copyright (c) 2017 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.
|
|
*/
|
|
|
|
#ifndef REMILL_ARCH_X86_SEMANTICS_MISC_H_
|
|
#define REMILL_ARCH_X86_SEMANTICS_MISC_H_
|
|
|
|
namespace {
|
|
|
|
template <typename D, typename S>
|
|
DEF_SEM(LEA, D dst, S src) {
|
|
WriteZExt(dst, AddressOf(src));
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(LEAVE_16BIT) {
|
|
addr_t op_size = 2;
|
|
addr_t link_pointer = Read(REG_XBP);
|
|
addr_t base_pointer = Read(
|
|
ReadPtr<addr_t>(link_pointer _IF_32BIT(REG_SS_BASE)));
|
|
Write(REG_XBP, base_pointer);
|
|
Write(REG_XSP, UAdd(link_pointer, op_size));
|
|
return memory;
|
|
}
|
|
|
|
template <typename T>
|
|
DEF_SEM(LEAVE_FULL) {
|
|
addr_t op_size = TruncTo<addr_t>(sizeof(T));
|
|
addr_t link_pointer = Read(REG_XBP);
|
|
addr_t base_pointer = Read(
|
|
ReadPtr<addr_t>(link_pointer _IF_32BIT(REG_SS_BASE)));
|
|
Write(REG_XBP, base_pointer);
|
|
Write(REG_XSP, UAdd(link_pointer, op_size));
|
|
return memory;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
DEF_ISEL(LEA_GPRv_AGEN_32) = LEA<R32W, M8>;
|
|
IF_64BIT( DEF_ISEL(LEA_GPRv_AGEN_64) = LEA<R64W, M8>; )
|
|
|
|
DEF_ISEL(LEAVE_16) = LEAVE_16BIT;
|
|
DEF_ISEL_RI32or64(LEAVE, LEAVE_FULL);
|
|
|
|
namespace {
|
|
|
|
// TODO(pag): Handle the case where the operand size and address size disagree.
|
|
// This can happen when using the 66H or 67H prefixes to override the
|
|
// operand or address sizes. For example, and operand size of 32 with
|
|
// an address size of 16 will read `[BP]` instead of `[EBP]`, but the
|
|
// stack pointer will decrement by `4`.
|
|
template <typename T>
|
|
DEF_SEM(ENTER, I16 src1, I8 src2) {
|
|
addr_t op_size = sizeof(T);
|
|
addr_t alloc_size = ZExtTo<addr_t>(Read(src1));
|
|
addr_t nesting_level = ZExtTo<addr_t>(URem(Read(src2), 32_u8));
|
|
addr_t xsp_temp = Read(REG_XSP);
|
|
addr_t frame_temp = USub(xsp_temp, op_size);
|
|
addr_t next_xsp = USub(
|
|
USub(frame_temp, UMul(op_size, nesting_level)),
|
|
alloc_size);
|
|
|
|
// Detect failure. This should really happen at the end of `ENTER` but we
|
|
// do it here. This is why `frame_temp` is created before the `PUSH` of
|
|
// `RBP`, but displaced to mimic the `PUSH`.
|
|
Write(WritePtr<T>(next_xsp _IF_32BIT(REG_SS_BASE)),
|
|
Read(ReadPtr<T>(next_xsp _IF_32BIT(REG_SS_BASE))));
|
|
|
|
// Push `XBP`.
|
|
addr_t xbp_temp = Read(REG_XBP);
|
|
addr_t xsp_after_push = USub(xsp_temp, op_size);
|
|
Write(REG_XSP, xsp_after_push);
|
|
Write(WritePtr<T>(xsp_after_push _IF_32BIT(REG_SS_BASE)),
|
|
TruncTo<T>(xbp_temp));
|
|
xsp_temp = xsp_after_push;
|
|
|
|
if (nesting_level) {
|
|
if (1 < nesting_level) {
|
|
_Pragma("unroll")
|
|
for (addr_t i = 1; i <= (nesting_level - 1); ++i) {
|
|
xbp_temp = USub(xbp_temp, op_size); // TODO(pag): Handle 67H prefix.
|
|
|
|
// Copy the display entry to the stack.
|
|
xsp_after_push = USub(xsp_temp, op_size);
|
|
Write(WritePtr<T>(xsp_after_push _IF_32BIT(REG_SS_BASE)),
|
|
Read(ReadPtr<T>(xbp_temp _IF_32BIT(REG_SS_BASE))));
|
|
xsp_temp = xsp_after_push;
|
|
}
|
|
}
|
|
|
|
xsp_temp = xsp_after_push;
|
|
xsp_after_push = USub(xsp_temp, op_size);
|
|
Write(WritePtr<addr_t>(xsp_after_push _IF_32BIT(REG_SS_BASE)), frame_temp);
|
|
xsp_temp = xsp_after_push;
|
|
}
|
|
|
|
Write(REG_XBP, frame_temp);
|
|
Write(REG_XSP, USub(xsp_temp, alloc_size));
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoNothing) {
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoCLFLUSH_MEMmprefetch, M8) {
|
|
return memory;
|
|
}
|
|
|
|
|
|
// Good reference for memory barriers and their relationships to instructions:
|
|
// http://g.oswego.edu/dl/jmm/cookbook.html
|
|
|
|
DEF_SEM(DoMFENCE) {
|
|
BarrierStoreLoad();
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoSFENCE) {
|
|
BarrierStoreStore();
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoLFENCE) {
|
|
BarrierLoadLoad();
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoXLAT) {
|
|
addr_t base = Read(REG_XBX);
|
|
addr_t offset = ZExtTo<addr_t>(Read(REG_AL));
|
|
Write(REG_AL, Read(
|
|
ReadPtr<uint8_t>(UAdd(base, offset) _IF_32BIT(REG_DS_BASE))));
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoCPUID) {
|
|
return __remill_sync_hyper_call(memory, state, SyncHyperCall::kX86CPUID);
|
|
}
|
|
} // namespace
|
|
|
|
DEF_ISEL(ENTER_IMMw_IMMb_16) = ENTER<uint16_t>;
|
|
IF_32BIT(DEF_ISEL(ENTER_IMMw_IMMb_32) = ENTER<uint32_t>;)
|
|
IF_64BIT(DEF_ISEL(ENTER_IMMw_IMMb_64) = ENTER<uint64_t>;)
|
|
|
|
// A `NOP` with a `REP` prefix for hinting. Used for busy-wait loops.
|
|
DEF_ISEL(PAUSE) = DoNothing;
|
|
|
|
// A kind of NOP.
|
|
DEF_ISEL(CLFLUSH_MEMmprefetch) = DoCLFLUSH_MEMmprefetch;
|
|
|
|
DEF_ISEL(MFENCE) = DoMFENCE;
|
|
|
|
DEF_ISEL(SFENCE) = DoSFENCE;
|
|
|
|
DEF_ISEL(LFENCE) = DoLFENCE;
|
|
|
|
DEF_ISEL(XLAT) = DoXLAT;
|
|
|
|
DEF_ISEL(CPUID) = DoCPUID;
|
|
|
|
DEF_ISEL(UD2) = DoNothing;
|
|
|
|
DEF_ISEL(HLT) = DoNothing;
|
|
|
|
/*
|
|
230 INVPCID INVPCID_GPR64_MEMdq MISC INVPCID INVPCID ATTRIBUTES: NOTSX RING0
|
|
231 INVPCID INVPCID_GPR32_MEMdq MISC INVPCID INVPCID ATTRIBUTES: NOTSX RING0
|
|
639 MONITOR MONITOR MISC SSE3 SSE3 ATTRIBUTES: NOTSX RING0
|
|
1924 MWAIT MWAIT MISC SSE3 SSE3 ATTRIBUTES: NOTSX RING0
|
|
*/
|
|
|
|
#endif // REMILL_ARCH_X86_SEMANTICS_MISC_H_
|