Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion build-coredistools.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,30 @@ set TargetOSArchitecture=%1

if /i "%TargetOSArchitecture%" == "windows-arm" (
set GeneratorPlatform=ARM
set LLVMDefaultTargetTriple=thumbv7-pc-windows-msvc
set LLVMHostTriple=arm-pc-windows-msvc
set LLVMTargetsToBuild=ARM
) else if /i "%TargetOSArchitecture%" == "windows-arm64" (
set GeneratorPlatform=ARM64
set LLVMHostTriple=aarch64-pc-windows-msvc
set LLVMTargetsToBuild=AArch64
) else if /i "%TargetOSArchitecture%" == "windows-x64" (
set GeneratorPlatform=x64
set LLVMHostTriple=x86_64-pc-windows-msvc
set LLVMTargetsToBuild=AArch64;X86
) else if /i "%TargetOSArchitecture%" == "windows-x86" (
set GeneratorPlatform=Win32
set LLVMHostTriple=i686-pc-windows-msvc
set LLVMTargetsToBuild=ARM;X86
) else (
echo "Unknown target OS and architecture: %TargetOSArchitecture%"
exit /b 1
)

if not defined LLVMDefaultTargetTriple (
set LLVMDefaultTargetTriple=%LLVMHostTriple%
)

where /q llvm-tblgen.exe

if %ERRORLEVEL% neq 0 (
Expand All @@ -40,11 +53,15 @@ cmake.exe ^
-G "Visual Studio 16 2019" ^
-A %GeneratorPlatform% ^
-DCMAKE_INSTALL_PREFIX="%RootDirectory%\" ^
-DLLVM_DEFAULT_TARGET_TRIPLE=%LLVMDefaultTargetTriple% ^
-DLLVM_EXTERNAL_PROJECTS=coredistools ^
-DLLVM_EXTERNAL_COREDISTOOLS_SOURCE_DIR="%SourcesDirectory%\coredistools" ^
-DLLVM_HOST_TRIPLE=%LLVMHostTriple% ^
-DLLVM_TABLEGEN="%LLVMTableGen%" ^
-DLLVM_TARGETS_TO_BUILD=AArch64;ARM;X86 ^
-DLLVM_TARGETS_TO_BUILD=%LLVMTargetsToBuild% ^
-DLLVM_TOOL_COREDISTOOLS_BUILD=ON ^
-DLLVM_USE_CRT_DEBUG=MTd ^
-DLLVM_USE_CRT_RELEASE=MT ^
"%SourcesDirectory%\llvm-project\llvm"

popd
Expand Down
20 changes: 13 additions & 7 deletions build-coredistools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,21 @@ CrossRootfsDirectory=$2
case "$TargetOSArchitecture" in
linux-arm)
CrossCompiling=1
TargetTriple=arm-linux-gnueabihf
LLVMDefaultTargetTriple=thumbv7-linux-gnueabihf
LLVMHostTriple=arm-linux-gnueabihf
LLVMTargetsToBuild=ARM
;;

linux-arm64)
CrossCompiling=1
TargetTriple=aarch64-linux-gnu
LLVMDefaultTargetTriple=aarch64-linux-gnu
LLVMHostTriple=aarch64-linux-gnu
LLVMTargetsToBuild=AArch64
;;

linux-x64|macos-x64)
CrossCompiling=0
LLVMTargetsToBuild="AArch64;X86"
;;

*)
Expand All @@ -43,17 +48,18 @@ if [ "$CrossCompiling" -eq 1 ]; then
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CROSSCOMPILING=ON \
-DCMAKE_C_COMPILER=$(which clang) \
-DCMAKE_C_FLAGS="-target $TargetTriple --sysroot=$CrossRootfsDirectory" \
-DCMAKE_C_FLAGS="-target $LLVMHostTriple --sysroot=$CrossRootfsDirectory" \
-DCMAKE_CXX_COMPILER=$(which clang++) \
-DCMAKE_CXX_FLAGS="-target $TargetTriple --sysroot=$CrossRootfsDirectory" \
-DCMAKE_CXX_FLAGS="-target $LLVMHostTriple --sysroot=$CrossRootfsDirectory" \
-DCMAKE_INCLUDE_PATH=$CrossRootfsDirectory/usr/include \
-DCMAKE_INSTALL_PREFIX=$RootDirectory \
-DCMAKE_LIBRARY_PATH=$CrossRootfsDirectory/usr/lib/$TargetTriple \
-DCMAKE_LIBRARY_PATH=$CrossRootfsDirectory/usr/lib/$LLVMHostTriple \
-DLLVM_DEFAULT_TARGET_TRIPLE=$LLVMDefaultTargetTriple \
-DLLVM_EXTERNAL_PROJECTS=coredistools \
-DLLVM_EXTERNAL_COREDISTOOLS_SOURCE_DIR=$SourcesDirectory/coredistools \
-DLLVM_HOST_TRIPLE=$TargetTriple \
-DLLVM_HOST_TRIPLE=$LLVMHostTriple \
-DLLVM_TABLEGEN=$(which llvm-tblgen) \
-DLLVM_TARGETS_TO_BUILD="AArch64;ARM;X86" \
-DLLVM_TARGETS_TO_BUILD=$LLVMTargetsToBuild \
-DLLVM_TOOL_COREDISTOOLS_BUILD=ON \
$SourcesDirectory/llvm-project/llvm
else
Expand Down
108 changes: 101 additions & 7 deletions src/coredistools/coredistools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DataTypes.h"
#include <inttypes.h>
#include <stdarg.h>

#define DllInterfaceExporter
Expand Down Expand Up @@ -182,6 +183,8 @@ struct CorDisasm {
protected:
enum TargetArch TheTargetArch;
const PrintControl *Print;
bool isThumb2MoveImmediateOpcode(unsigned int opcode) const;
bool isThumb2MoveTopOpcode(unsigned int opcode) const;

private:
bool setTarget();
Expand All @@ -208,6 +211,11 @@ struct CorDisasm {

static const int X86NumPrefixes = 19;
static const OpcodeMap X86Prefix[X86NumPrefixes];

// The following constants is a workaround and the opcode numbers
// were copied from TableGen-erated lib/Target/ARM/ARMGenInstrInfo.inc
static const unsigned int Thumb2MoveImmediateOpcode = 3887; // Corresponds to t2MOVi16
static const unsigned int Thumb2MoveTopOpcode = 3885; // Correspond to t2MOVTi16
};

struct CorAsmDiff : public CorDisasm {
Expand All @@ -224,6 +232,8 @@ struct CorAsmDiff : public CorDisasm {
bool fail(const char *Mesg, const BlockIterator &Left,
const BlockIterator &Right) const;

bool tryDecodeThumb2MoveImm32(const BlockIterator& Iter, unsigned int& Reg, unsigned int& Imm32) const;

OffsetComparator Comparator;
};

Expand Down Expand Up @@ -281,7 +291,7 @@ bool CorDisasm::setTarget() {
break;

case Target_Thumb:
TheTriple.setArch(Triple::thumb);
TheTriple.setArchName("thumbv7");
break;
case Target_Arm64:
TheTriple.setArch(Triple::aarch64);
Expand Down Expand Up @@ -463,7 +473,7 @@ void CorDisasm::dumpInstruction(const BlockIterator &BIter) const {
string buffer;
raw_string_ostream OS(buffer);

OS << format("%8llx: ", BIter.Addr);
OS << format("%" PRIxPTR ": ", BIter.Addr);
dumpBytes(ArrayRef<uint8_t>(BIter.Ptr, InstSize), OS);

if ((TheTargetArch == Target_X86) || (TheTargetArch == Target_X64)) {
Expand All @@ -480,6 +490,12 @@ void CorDisasm::dumpInstruction(const BlockIterator &BIter) const {
" "};
OS << (Padding[(InstSize < 7) ? (7 - InstSize) : 0]);
}
else if (TheTargetArch == Target_Thumb) {
// Thumb-2 encoding has 32-bit instructions and 16-bit instructions.
if (InstSize == 2) {
OS << " ";
}
}

IP->printInst(&BIter.Inst, OS, "", *STI);
Print->Dump(OS.str().c_str());
Expand All @@ -489,8 +505,8 @@ void CorDisasm::dumpBlock(const BlockInfo &Block) const {
BlockIterator BIter(Block);

Print->Dump("-----------------------------------------------");
Print->Dump("Block: %s\nSize: %lu\nAddress: %8llx\nCodePtr: %8llx",
BIter.Name, BIter.BlockSize, BIter.Addr, BIter.Ptr);
Print->Dump("Block: %s\nSize: %" PRIu64 "\nAddress: %" PRIxPTR "\nCodePtr: %" PRIxPTR,
BIter.Name, BIter.BlockSize, BIter.Addr, (uintptr_t)BIter.Ptr);
Print->Dump("-----------------------------------------------");

while (!BIter.isEmpty()) {
Expand All @@ -503,6 +519,57 @@ void CorDisasm::dumpBlock(const BlockInfo &Block) const {
Print->Dump("-----------------------------------------------");
}

bool CorDisasm::isThumb2MoveImmediateOpcode(unsigned int Opcode) const {
return (Opcode == Thumb2MoveImmediateOpcode);
}

bool CorDisasm::isThumb2MoveTopOpcode(unsigned int Opcode) const {
return (Opcode == Thumb2MoveTopOpcode);
}

bool CorAsmDiff::tryDecodeThumb2MoveImm32(const BlockIterator& Curr, unsigned int& Reg, unsigned int& Imm32) const {
assert(Curr.isDecoded());

if (!isThumb2MoveImmediateOpcode(Curr.Inst.getOpcode())) {
return false;
}

BlockIterator Next = Curr;

Next.advance();

if (Next.isEmpty()) {
return false;
}

decodeInstruction(Next);

if (!Next.isDecoded()) {
return false;
}

if (!isThumb2MoveTopOpcode(Next.Inst.getOpcode())) {
return false;
}

const MCInst& MovImm = Curr.Inst;
const MCInst& MovTop = Next.Inst;

if (MovImm.getOperand(0).getReg() != MovTop.getOperand(0).getReg()) {
return false;
}

Reg = MovImm.getOperand(0).getReg();

const unsigned Lo16 = (unsigned int)MovImm.getOperand(1).getImm();
const unsigned Hi16 = (unsigned int)MovTop.getOperand(2).getImm();

// Reconstruct 32-bit value that is loaded using movw/movt instruction pair.
Imm32 = Lo16 | (Hi16 << 16);

return true;
}

// Compares two code sections for syntactic equality. This is the core of the
// asm diffing logic.
//
Expand Down Expand Up @@ -554,6 +621,34 @@ bool CorAsmDiff::nearDiff(const BlockInfo &LeftBlock,
return fail("Instruction Size Mismatch", Left, Right);
}

if (TheTargetArch == Target_Thumb) {
unsigned int RegL = 0;
unsigned int RegR = 0;

unsigned int Imm32L = 0;
unsigned int Imm32R = 0;

// On Thumb2 movw/movt instruction pair can be used to load a 32-bit value to a register.
// If this is the case, we should treat such instruction pair as **one** pseudo-instruction and try decoding them together.
if (tryDecodeThumb2MoveImm32(Left, RegL, Imm32L) && tryDecodeThumb2MoveImm32(Right, RegR, Imm32R)) {
if ((RegL == RegR) && ((Imm32L == Imm32R) || Comparator(UserData, Left.BlockOffset(), Left.InstrSize, Imm32L, Imm32R))) {
// When movw/movt instructions pairs load the same or "equivalent" 32-bit values
// to the same register advance both iterators to the positions after movt.

Left.advance();
decodeInstruction(Left);
Left.advance();

Right.advance();
decodeInstruction(Right);
Right.advance();

continue;
}
// Otherwise, do nothing and allow the comparison below to fail.
}
}

// First, check to see if these instructions are actually identical.
// This is done 1) to avoid the detailed comparison of the fields of InstL
// and InstR if they are identical, and 2) because in the event that
Expand Down Expand Up @@ -613,8 +708,7 @@ bool CorAsmDiff::nearDiff(const BlockInfo &LeftBlock,
continue;
}

if (Comparator(UserData, Left.BlockOffset(), Left.InstrSize, ImmL,
ImmR)) {
if (Comparator(UserData, Left.BlockOffset(), Left.InstrSize, ImmL, ImmR)) {
// The client somehow thinks that these offsets are equivalent
continue;
}
Expand All @@ -637,7 +731,7 @@ bool BlockIterator::isBitwiseEqual(const BlockIterator &BIter) const {

bool CorAsmDiff::fail(const char *Mesg, const BlockIterator &Left,
const BlockIterator &Right) const {
Print->Log("%s @[%llx : %llx]", Mesg, Left.Addr, Right.Addr);
Print->Log("%s @[%" PRIxPTR " : %" PRIxPTR "]", Mesg, Left.Addr, Right.Addr);
return false;
}

Expand Down