Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[X86-64] Only treat PC-relative globals as memory content if they are dynamically relocated #121

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
22 changes: 10 additions & 12 deletions X86/X86MachineInstructionRaiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ using namespace llvm;
using namespace mctoll;
using namespace X86RegisterUtils;

std::set<std::string> X86MachineInstructionRaiser::DynRelocatedGlobalVariables;

// Constructor

X86MachineInstructionRaiser::X86MachineInstructionRaiser(MachineFunction &MF,
Expand Down Expand Up @@ -2083,18 +2085,14 @@ bool X86MachineInstructionRaiser::raiseMoveFromMemInstr(const MachineInstr &MI,
// Following are the exceptions when MemRefValue needs to be considered as
// memory content and not as memory reference.
if (IsPCRelMemRef) {
// If it is a PC-relative global variable with an initializer, it is memory
// content and should not be loaded from.
if (auto GV = dyn_cast<GlobalVariable>(MemRefValue))
LoadFromMemrefValue = !(GV->hasInitializer());
// If it is not a PC-relative constant expression accessed using
// GetElementPtrInst, it is memory content and should not be loaded from.
else {
const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(MemRefValue);
if (CExpr != nullptr) {
LoadFromMemrefValue =
(CExpr->getOpcode() == Instruction::GetElementPtr);
}
// If it is a PC-relative dynamically relocated global variable, it is
// memory content and should not be loaded from.
if (auto GV = dyn_cast<GlobalVariable>(MemRefValue)) {
LoadFromMemrefValue = !isDynRelocatedGlobalVariable(GV->getName().str());
// If it is not a PC-relative constant expression accessed using
// GetElementPtrInst, it is memory content and should not be loaded from.
} else if (auto *CExpr = dyn_cast<ConstantExpr>(MemRefValue)) {
LoadFromMemrefValue = (CExpr->getOpcode() == Instruction::GetElementPtr);
}
}

Expand Down
9 changes: 9 additions & 0 deletions X86/X86MachineInstructionRaiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ class X86MachineInstructionRaiser : public MachineInstructionRaiser {
// at the exit of the MBB.
std::map<int, MCPhysRegSizeMap> PerMBBDefinedPhysRegMap;

// Stores all global variables that are dynamically relocated, e.g. through PLT
// Usually these are global variables in shared objects
static std::set<std::string> DynRelocatedGlobalVariables;

static const uint8_t FPUSTACK_SZ = 8;
struct {
int8_t TOP;
Expand Down Expand Up @@ -220,6 +224,11 @@ class X86MachineInstructionRaiser : public MachineInstructionRaiser {
bool isEffectiveAddrValue(Value *Val);

std::vector<JumpTableInfo> jtList;

// Check if there exists a dynamically relocated variable with the given name
inline bool isDynRelocatedGlobalVariable(std::string Name) {
return DynRelocatedGlobalVariables.find(Name) != DynRelocatedGlobalVariables.end();
}
};

#endif // LLVM_TOOLS_LLVM_MCTOLL_X86_X86MACHINEINSTRUCTIONRAISER_H
29 changes: 14 additions & 15 deletions X86/X86MachineInstructionRaiserUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,18 @@ Value *X86MachineInstructionRaiser::loadMemoryRefValue(
// Following are the exceptions when MemRefValue needs to be considered as
// memory content and not as memory reference.
if (IsPCRelMemRef) {
// If it is a PC-relative global variable with an initializer, it is memory
// content and should not be loaded from.
if (auto GV = dyn_cast<GlobalVariable>(MemRefValue))
LoadFromMemrefValue = !(GV->hasInitializer());
// If it is a PC-relative dynamically relocated global variable, it is
// memory content and should not be loaded from.
if (auto GV = dyn_cast<GlobalVariable>(MemRefValue)) {
if (isDynRelocatedGlobalVariable(GV->getName().str())) {
LoadFromMemrefValue = false;
} else {
LoadFromMemrefValue = true;
}
// If it is not a PC-relative constant expression accessed using
// GetElementPtrInst, it is memory content and should not be loaded from.
else {
const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(MemRefValue);
if (CExpr != nullptr) {
LoadFromMemrefValue =
(CExpr->getOpcode() == Instruction::GetElementPtr);
}
} else if (auto *CExpr = dyn_cast<ConstantExpr>(MemRefValue)) {
LoadFromMemrefValue = (CExpr->getOpcode() == Instruction::GetElementPtr);
}
}

Expand Down Expand Up @@ -754,17 +754,16 @@ Value *X86MachineInstructionRaiser::createPCRelativeAccesssValue(
break;
}
}

Constant *GlobalInit;
if (IncludedFileInfo::IsExternalVariable(Symname->str())) {
GlobalInit = nullptr;
Lnkg = GlobalValue::ExternalLinkage;
} else if (DynRelocType == ELF::R_X86_64_GLOB_DAT) {
GlobalInit = ConstantInt::get(GlobalValTy, SymbVal);
DynRelocatedGlobalVariables.insert(Symname->str());
} else {
GlobalInit = (DynRelocType == ELF::R_X86_64_GLOB_DAT)
? ConstantInt::get(GlobalValTy, SymbVal)
: nullptr;
GlobalInit = nullptr;
}

auto GlobalVal = new GlobalVariable(*(MR->getModule()), GlobalValTy,
false /* isConstant */, Lnkg,
GlobalInit, Symname->data());
Expand Down
46 changes: 46 additions & 0 deletions test/asm_test/X86/raise-pcrel-global-variable.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// REQUIRES: x86_64-linux
// RUN: clang -O0 -o %t %s
// RUN: llvm-mctoll -d -I /usr/include/stdio.h %t
// RUN: clang -o %t-dis %t-dis.ll
// RUN: %t-dis 2>&1 | FileCheck %s
// CHECK: i = 0
// CHECK: i = 10
// CHECK-EMPTY

.text
.intel_syntax noprefix
.file "raise-call64r-float.s"

.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
movabs rdi, offset .L.str
mov esi, [rip + i]
mov al, 0
call printf

mov dword ptr [rip + i], 10

movabs rdi, offset .L.str
mov esi, [rip + i]
mov al, 0
call printf

xor rax, rax
ret


.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "i = %d\n"
.size .L.str, 8

.bss
.type i,@object
.globl i
.p2align 2
i:
.long 0
.size i, 4