aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2020-03-10 08:05:00 -0700
committerFangrui Song <maskray@google.com>2020-03-10 11:11:58 -0700
commita0c0389ffbb51d5f4417e926a5eb59d89fd2af05 (patch)
tree9c060fe74c03f209ec127dac5234c398a5abf114 /llvm/lib/Transforms/Utils/BuildLibCalls.cpp
parent9624beb38a46037f69362650a52e06d8be4fd006 (diff)
downloadllvm-a0c0389ffbb51d5f4417e926a5eb59d89fd2af05.zip
llvm-a0c0389ffbb51d5f4417e926a5eb59d89fd2af05.tar.gz
llvm-a0c0389ffbb51d5f4417e926a5eb59d89fd2af05.tar.bz2
[SimplifyLibcalls] Don't replace locked IO (fgetc/fgets/fputc/fputs/fread/fwrite) with unlocked IO (*_unlocked)
This essentially reverts some of the SimplifyLibcalls part changes of D45736 [SimplifyLibcalls] Replace locked IO with unlocked IO. C11 7.21.5.2 The fflush function > If stream is a null pointer, the fflush function performs this flushing action on all streams for which the behavior is defined above. i.e. fopen'ed FILE* is inherently captured. POSIX.1-2017 getc_unlocked, getchar_unlocked, putc_unlocked, putchar_unlocked - stdio with explicit client locking > These functions can safely be used in a multi-threaded program if and only if they are called while the invoking thread owns the ( FILE *) object, as is the case after a successful call to the flockfile() or ftrylockfile() functions. After a thread fopen'ed a FILE*, when it is calling foobar() which is now replaced by foobar_unlocked(), if another thread is concurrently calling fflush(0), the behavior is undefined. C11 7.22.4.4 The exit function > Next, all open streams with unwritten buffered data are flushed, all open streams are closed, and all files created by the tmpfile function are removed. The replacement is only feasible if the program is single threaded, or exit or fflush(0) is never called. See also http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20180528/556615.html for how the replacement makes libc interceptors difficult to implement. dalias: in a worst case, it's unbounded data corruption because of concurrent access to pointers without synchronization. f->wpos or rpos could get outside of the buffer, thread A could do f->wpos += j after knowing j is in bounds, while thread B also changes it concurrently. This can produce exploitable conditions depending on libc internals. Revert the SimplifyLibcalls part change because the cons obviously overweigh the pros. Even when the replacement is feasible, the benefit is indemonstrable, more so in an application instead of an artificial glibc benchmark. Theoretically the replacement could be beneficial when calling getc_unlocked/putc_unlocked in a loop, but then it is better using a blocked IO operation and the user is likely aware of that. The function attribute inference is still useful and thus kept. Reviewed By: xbolva00 Differential Revision: https://reviews.llvm.org/D75933
Diffstat (limited to 'llvm/lib/Transforms/Utils/BuildLibCalls.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/BuildLibCalls.cpp124
1 files changed, 0 insertions, 124 deletions
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 40378c1..a385b08 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1188,26 +1188,6 @@ Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilderBase &B,
return CI;
}
-Value *llvm::emitFPutCUnlocked(Value *Char, Value *File, IRBuilderBase &B,
- const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fputc_unlocked))
- return nullptr;
-
- Module *M = B.GetInsertBlock()->getModule();
- StringRef FPutcUnlockedName = TLI->getName(LibFunc_fputc_unlocked);
- FunctionCallee F = M->getOrInsertFunction(FPutcUnlockedName, B.getInt32Ty(),
- B.getInt32Ty(), File->getType());
- if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FPutcUnlockedName, *TLI);
- Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/ true, "chari");
- CallInst *CI = B.CreateCall(F, {Char, File}, FPutcUnlockedName);
-
- if (const Function *Fn =
- dyn_cast<Function>(F.getCallee()->stripPointerCasts()))
- CI->setCallingConv(Fn->getCallingConv());
- return CI;
-}
-
Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilderBase &B,
const TargetLibraryInfo *TLI) {
if (!TLI->has(LibFunc_fputs))
@@ -1227,25 +1207,6 @@ Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilderBase &B,
return CI;
}
-Value *llvm::emitFPutSUnlocked(Value *Str, Value *File, IRBuilderBase &B,
- const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fputs_unlocked))
- return nullptr;
-
- Module *M = B.GetInsertBlock()->getModule();
- StringRef FPutsUnlockedName = TLI->getName(LibFunc_fputs_unlocked);
- FunctionCallee F = M->getOrInsertFunction(FPutsUnlockedName, B.getInt32Ty(),
- B.getInt8PtrTy(), File->getType());
- if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FPutsUnlockedName, *TLI);
- CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, FPutsUnlockedName);
-
- if (const Function *Fn =
- dyn_cast<Function>(F.getCallee()->stripPointerCasts()))
- CI->setCallingConv(Fn->getCallingConv());
- return CI;
-}
-
Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilderBase &B,
const DataLayout &DL, const TargetLibraryInfo *TLI) {
if (!TLI->has(LibFunc_fwrite))
@@ -1310,88 +1271,3 @@ Value *llvm::emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs,
return CI;
}
-
-Value *llvm::emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
- IRBuilderBase &B, const DataLayout &DL,
- const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fwrite_unlocked))
- return nullptr;
-
- Module *M = B.GetInsertBlock()->getModule();
- LLVMContext &Context = B.GetInsertBlock()->getContext();
- StringRef FWriteUnlockedName = TLI->getName(LibFunc_fwrite_unlocked);
- FunctionCallee F = M->getOrInsertFunction(
- FWriteUnlockedName, DL.getIntPtrType(Context), B.getInt8PtrTy(),
- DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType());
-
- if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FWriteUnlockedName, *TLI);
- CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, N, File});
-
- if (const Function *Fn =
- dyn_cast<Function>(F.getCallee()->stripPointerCasts()))
- CI->setCallingConv(Fn->getCallingConv());
- return CI;
-}
-
-Value *llvm::emitFGetCUnlocked(Value *File, IRBuilderBase &B,
- const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fgetc_unlocked))
- return nullptr;
-
- Module *M = B.GetInsertBlock()->getModule();
- StringRef FGetCUnlockedName = TLI->getName(LibFunc_fgetc_unlocked);
- FunctionCallee F = M->getOrInsertFunction(FGetCUnlockedName, B.getInt32Ty(),
- File->getType());
- if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FGetCUnlockedName, *TLI);
- CallInst *CI = B.CreateCall(F, File, FGetCUnlockedName);
-
- if (const Function *Fn =
- dyn_cast<Function>(F.getCallee()->stripPointerCasts()))
- CI->setCallingConv(Fn->getCallingConv());
- return CI;
-}
-
-Value *llvm::emitFGetSUnlocked(Value *Str, Value *Size, Value *File,
- IRBuilderBase &B, const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fgets_unlocked))
- return nullptr;
-
- Module *M = B.GetInsertBlock()->getModule();
- StringRef FGetSUnlockedName = TLI->getName(LibFunc_fgets_unlocked);
- FunctionCallee F =
- M->getOrInsertFunction(FGetSUnlockedName, B.getInt8PtrTy(),
- B.getInt8PtrTy(), B.getInt32Ty(), File->getType());
- inferLibFuncAttributes(M, FGetSUnlockedName, *TLI);
- CallInst *CI =
- B.CreateCall(F, {castToCStr(Str, B), Size, File}, FGetSUnlockedName);
-
- if (const Function *Fn =
- dyn_cast<Function>(F.getCallee()->stripPointerCasts()))
- CI->setCallingConv(Fn->getCallingConv());
- return CI;
-}
-
-Value *llvm::emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
- IRBuilderBase &B, const DataLayout &DL,
- const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fread_unlocked))
- return nullptr;
-
- Module *M = B.GetInsertBlock()->getModule();
- LLVMContext &Context = B.GetInsertBlock()->getContext();
- StringRef FReadUnlockedName = TLI->getName(LibFunc_fread_unlocked);
- FunctionCallee F = M->getOrInsertFunction(
- FReadUnlockedName, DL.getIntPtrType(Context), B.getInt8PtrTy(),
- DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType());
-
- if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FReadUnlockedName, *TLI);
- CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, N, File});
-
- if (const Function *Fn =
- dyn_cast<Function>(F.getCallee()->stripPointerCasts()))
- CI->setCallingConv(Fn->getCallingConv());
- return CI;
-}