Open Quuxplusone opened 9 years ago
Here is a C program, which does fail with the error:
LLVM ERROR: unsupported GC: shadow-stack
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
LLVMModuleRef mod = LLVMModuleCreateWithName("my_module");
LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() };
LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, 0);
LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type);
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, entry);
LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp");
LLVMBuildRet(builder, tmp);
char *error = NULL;
LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
LLVMDisposeMessage(error);
LLVMExecutionEngineRef engine;
error = NULL;
LLVMLinkInMCJIT();
LLVMInitializeX86Target();
LLVMInitializeX86TargetInfo();
LLVMInitializeX86TargetMC();
LLVMInitializeX86AsmPrinter();
LLVMSetGC(sum, "shadow-stack");
if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) {
fprintf(stderr, "failed to create execution engine\n");
abort();
}
if (error) {
fprintf(stderr, "error: %s\n", error);
LLVMDisposeMessage(error);
exit(EXIT_FAILURE);
}
if (argc < 3) {
fprintf(stderr, "usage: %s x y\n", argv[0]);
exit(EXIT_FAILURE);
}
long long x = strtoll(argv[1], NULL, 10);
long long y = strtoll(argv[2], NULL, 10);
LLVMGenericValueRef args[] = {
LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0),
LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0)
};
LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args);
printf("%d\n", (int)LLVMGenericValueToInt(res, 0));
// Write out bitcode to file
if (LLVMWriteBitcodeToFile(mod, "sum.bc") != 0) {
fprintf(stderr, "error writing bitcode to file, skipping\n");
}
LLVMDisposeBuilder(builder);
LLVMDisposeExecutionEngine(engine);
}
Here is a C++ version, with a little bit of C bindings mixed, but I don't think
it has anything to do with the binding. The dictionary that has gc strategies
seems to be empty.
// Generated by llvm2cpp - DO NOT MODIFY!
#include <llvm/Pass.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/CallingConv.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/IRPrintingPasses.h>
#include <llvm/IR/InlineAsm.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/MathExtras.h>
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
#include <algorithm>
using namespace llvm;
Module* makeLLVMModule();
int main(int argc, char**argv) {
Module* Mod = makeLLVMModule();
LLVMDumpModule(wrap(Mod));
LLVMLinkInMCJIT();
LLVMInitializeX86Target();
LLVMInitializeX86TargetInfo();
LLVMInitializeX86TargetMC();
LLVMInitializeX86AsmPrinter();
LLVMExecutionEngineRef engine;
LLVMMCJITCompilerOptions options;
int optionsSize = (4 * sizeof(int)) + sizeof(int *); // LLVMMCJITCompilerOptions has 4 ints and a pointer
LLVMInitializeMCJITCompilerOptions(&options, optionsSize);
char** error;
LLVMCreateMCJITCompilerForModule(&engine, wrap(Mod), &options, optionsSize, error);
LLVMGetPointerToGlobal(engine, wrap(Mod->getFunction("sum")));
return 0;
}
Module* makeLLVMModule() {
// Module Construction
Module* mod = new Module("C:/abc.bc", getGlobalContext());
mod->setDataLayout("");
mod->setTargetTriple("x86_64-ellcc-linux");
// Type Definitions
std::vector<Type*>FuncTy_0_args;
FuncTy_0_args.push_back(IntegerType::get(mod->getContext(), 32));
FuncTy_0_args.push_back(IntegerType::get(mod->getContext(), 32));
FunctionType* FuncTy_0 = FunctionType::get(
/*Result=*/IntegerType::get(mod->getContext(), 32),
/*Params=*/FuncTy_0_args,
/*isVarArg=*/false);
// Function Declarations
Function* func_sum = mod->getFunction("sum");
if (!func_sum) {
func_sum = Function::Create(
/*Type=*/FuncTy_0,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"sum", mod);
func_sum->setCallingConv(CallingConv::C);
func_sum->setGC("shadow-stack");
}
AttributeSet func_sum_PAL;
{
SmallVector<AttributeSet, 4> Attrs;
AttributeSet PAS;
{
AttrBuilder B;
B.addAttribute(Attribute::NoUnwind);
B.addAttribute(Attribute::ReadNone);
PAS = AttributeSet::get(mod->getContext(), ~0U, B);
}
Attrs.push_back(PAS);
func_sum_PAL = AttributeSet::get(mod->getContext(), Attrs);
}
func_sum->setAttributes(func_sum_PAL);
// Global Variable Declarations
// Constant Definitions
// Global Variable Definitions
// Function Definitions
// Function: sum (func_sum)
{
Function::arg_iterator args = func_sum->arg_begin();
Value* int32_a = args++;
int32_a->setName("a");
Value* int32_b = args++;
int32_b->setName("b");
BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry", func_sum, 0);
// Block entry (label_entry)
BinaryOperator* int32_add = BinaryOperator::Create(Instruction::Add, int32_b, int32_a, "add", label_entry);
ReturnInst::Create(mod->getContext(), int32_add, label_entry);
}
return mod;
}
Attached linkShadowStackGC.diff
(1109 bytes, text/plain): Patch for exposing llvm::linkShadowStackGC()
linkShadowStackGC.diff
(1109 bytes, text/plain)