[llvm-branch-commits] [compiler-rt] f625ab2 - [sanitizer] Intercept glibc's argp_parse()
Author: Ilya Leoshkevich Date: 2023-02-24T14:15:58+01:00 New Revision: f625ab2c6943b1c381ff17fed0f4d5abc0bc10f3 URL: https://github.com/llvm/llvm-project/commit/f625ab2c6943b1c381ff17fed0f4d5abc0bc10f3 DIFF: https://github.com/llvm/llvm-project/commit/f625ab2c6943b1c381ff17fed0f4d5abc0bc10f3.diff LOG: [sanitizer] Intercept glibc's argp_parse() Glibc provides the argp_parse() function for parsing command line arguments [1]. Indicate that argc/argv are read from and arg_index is written to. Strictly speaking, we also need to indicate that argp is read from, but this would require describing its layout, and most people use a static initializer there, so it's not worth the effort. [1] https://www.gnu.org/software/libc/manual/html_node/Argp.html Differential Revision: https://reviews.llvm.org/D143330 Added: compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c Modified: compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h Removed: diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 9fc56238a64fc..51703a34f0e9b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -10375,6 +10375,25 @@ INTERCEPTOR(void, hexdump, const void *ptr, int length, const char *header, int #define INIT_HEXDUMP #endif +#if SANITIZER_INTERCEPT_ARGP_PARSE +INTERCEPTOR(int, argp_parse, const struct argp *argp, int argc, char **argv, +unsigned flags, int *arg_index, void *input) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, argp_parse, argp, argc, argv, flags, arg_index, + input); + for (int i = 0; i < argc; i++) +COMMON_INTERCEPTOR_READ_RANGE(ctx, argv[i], internal_strlen(argv[i]) + 1); + int res = REAL(argp_parse)(argp, argc, argv, flags, arg_index, input); + if (!res && arg_index) +COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg_index, sizeof(int)); + return res; +} + +#define INIT_ARGP_PARSE COMMON_INTERCEPT_FUNCTION(argp_parse); +#else +#define INIT_ARGP_PARSE +#endif + #include "sanitizer_common_interceptors_netbsd_compat.inc" static void InitializeCommonInterceptors() { @@ -10694,6 +10713,7 @@ static void InitializeCommonInterceptors() { INIT_UNAME; INIT___XUNAME; INIT_HEXDUMP; + INIT_ARGP_PARSE; INIT___PRINTF_CHK; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 814ff462d1cf5..eb39fabfd5983 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -592,6 +592,7 @@ #define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD #define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD #define SANITIZER_INTERCEPT_HEXDUMP SI_FREEBSD +#define SANITIZER_INTERCEPT_ARGP_PARSE SI_GLIBC // This macro gives a way for downstream users to override the above // interceptor macros irrespective of the platform they are on. They have diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c new file mode 100644 index 0..b3e57cf5c8971 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c @@ -0,0 +1,57 @@ +// RUN: %clang %s -o %t && %run %t -o baz + +#include +#include +#include +#include + +struct test { + const char *option_value; +}; + +static const struct argp_option options[] = { +{"option", 'o', "OPTION", 0, "Option", 0}, +{NULL, 0, NULL, 0, NULL, 0}, +}; + +static error_t parser(int key, char *arg, struct argp_state *state) { + if (key == 'o') { +((struct test *)(state->input))->option_value = arg; +return 0; + } + return ARGP_ERR_UNKNOWN; +} + +static struct argp argp = {.options = options, .parser = parser}; + +void test_nulls(char *argv0) { + char *argv[] = {argv0, NULL}; + int res = argp_parse(NULL, 1, argv, 0, NULL, NULL); + assert(res == 0); +} + +void test_synthetic(char *argv0) { + char *argv[] = {argv0, "-o", "foo", "bar", NULL}; + struct test t = {NULL}; + int arg_index; + int res = argp_parse(&argp, 4, argv, 0, &arg_index, &t); + assert(res == 0); + assert(arg_index == 3); + assert(strcmp(t.option_value, "foo") == 0); +} + +void test_real(int argc, char **argv) { + struct test t = {NULL}; + int arg_index; + int res = argp_parse(&argp, argc, argv, 0, &arg_index, &t); + assert(res == 0); + assert(arg_index == 3); + assert(strcmp(t.option_value, "baz") == 0); +} + +int main(int argc, char **argv) { + test_nulls(argv[0]); + test_synthetic(argv[0]); + test_real(argc, argv); + return EXIT_SUCCESS; +} ___
[llvm-branch-commits] [clang] e8559b2 - endbr
Author: Ilya Leoshkevich Date: 2023-02-24T19:09:23+01:00 New Revision: e8559b2e524b9ee0b6f3fa86643a9c05037ebcc4 URL: https://github.com/llvm/llvm-project/commit/e8559b2e524b9ee0b6f3fa86643a9c05037ebcc4 DIFF: https://github.com/llvm/llvm-project/commit/e8559b2e524b9ee0b6f3fa86643a9c05037ebcc4.diff LOG: endbr Added: llvm/lib/Target/SystemZ/SystemZEndbr.cpp Modified: clang/lib/Basic/Targets/SystemZ.h llvm/lib/Target/SystemZ/CMakeLists.txt llvm/lib/Target/SystemZ/SystemZ.h llvm/lib/Target/SystemZ/SystemZInstrInfo.td llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp Removed: diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index 3df4284d4c4f4..4c516a5196bf8 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -209,6 +209,11 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { int getEHDataRegisterNumber(unsigned RegNo) const override { return RegNo < 4 ? 6 + RegNo : -1; } + + bool + checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override { +return true; + }; }; } // namespace targets } // namespace clang diff --git a/llvm/lib/Target/SystemZ/CMakeLists.txt b/llvm/lib/Target/SystemZ/CMakeLists.txt index ba845a74949fa..4de38ff391587 100644 --- a/llvm/lib/Target/SystemZ/CMakeLists.txt +++ b/llvm/lib/Target/SystemZ/CMakeLists.txt @@ -20,6 +20,7 @@ add_llvm_target(SystemZCodeGen SystemZConstantPoolValue.cpp SystemZCopyPhysRegs.cpp SystemZElimCompare.cpp + SystemZEndbr.cpp SystemZFrameLowering.cpp SystemZHazardRecognizer.cpp SystemZISelDAGToDAG.cpp diff --git a/llvm/lib/Target/SystemZ/SystemZ.h b/llvm/lib/Target/SystemZ/SystemZ.h index cdd2850ad8e17..4463e1231b104 100644 --- a/llvm/lib/Target/SystemZ/SystemZ.h +++ b/llvm/lib/Target/SystemZ/SystemZ.h @@ -197,6 +197,7 @@ FunctionPass *createSystemZLDCleanupPass(SystemZTargetMachine &TM); FunctionPass *createSystemZCopyPhysRegsPass(SystemZTargetMachine &TM); FunctionPass *createSystemZPostRewritePass(SystemZTargetMachine &TM); FunctionPass *createSystemZTDCPass(); +FunctionPass *createSystemZEndbrPass(); void initializeSystemZCopyPhysRegsPass(PassRegistry &); void initializeSystemZDAGToDAGISelPass(PassRegistry &); diff --git a/llvm/lib/Target/SystemZ/SystemZEndbr.cpp b/llvm/lib/Target/SystemZ/SystemZEndbr.cpp new file mode 100644 index 0..1d6119de4cd36 --- /dev/null +++ b/llvm/lib/Target/SystemZ/SystemZEndbr.cpp @@ -0,0 +1,66 @@ +//=== SystemZEndbr.cpp - --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "SystemZ.h" +#include "SystemZSubtarget.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" + +using namespace llvm; + +#define DEBUG_TYPE "systemz-endbr" + +namespace { +class SystemzEndbrPass : public MachineFunctionPass { +public: + SystemzEndbrPass() : MachineFunctionPass(ID) {} + + StringRef getPassName() const override { +return "SystemZ ENDBR"; + } + + bool runOnMachineFunction(MachineFunction &MF) override; + +private: + static char ID; +}; +} + +FunctionPass *llvm::createSystemZEndbrPass() { + return new SystemzEndbrPass(); +} + +char SystemzEndbrPass::ID = 0; + +bool SystemzEndbrPass::runOnMachineFunction(MachineFunction &MF) { + if (!MF.getMMI().getModule()->getModuleFlag("cf-protection-branch")) +return false; + + SmallPtrSet JumpTableTargets; + if (const MachineJumpTableInfo *JTI = MF.getJumpTableInfo()) +for (const MachineJumpTableEntry &JTE : JTI->getJumpTables()) + for (const MachineBasicBlock *MBB : JTE.MBBs) +JumpTableTargets.insert(MBB); + + const SystemZSubtarget &SubTarget = MF.getSubtarget(); + const SystemZInstrInfo *TII = SubTarget.getInstrInfo(); + int Count = 0; + for (MachineBasicBlock &MBB : MF) { +if (&MBB == &MF.front() || +MBB.hasAddressTaken() || +MBB.isEHPad() || +JumpTableTargets.count(&MBB)) { + MachineBasicBlock::iterator I = MBB.begin(); + BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(SystemZ::ENDBR)); + Count++; +} + } + + return Count; +} diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index c53cb7cadadb9..69fa5de664c23 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -124,6 +124,12 @@ def JNOP : InstAlias<"jnop\t$RI2", (BRCAsm 0, brtarget16:$RI2), 0>; // jgnop on att ; jlnop on hlasm def JGNOP : InstAlias<"{jgnop|jlnop}\t$RI2", (BRCL
[llvm-branch-commits] [llvm] d58f112 - Prevent FENTRY_CALL reordering
Author: Ilya Leoshkevich Date: 2020-12-09T00:59:01+01:00 New Revision: d58f112ce03877f73200591cd3c9b38e41e46afe URL: https://github.com/llvm/llvm-project/commit/d58f112ce03877f73200591cd3c9b38e41e46afe DIFF: https://github.com/llvm/llvm-project/commit/d58f112ce03877f73200591cd3c9b38e41e46afe.diff LOG: Prevent FENTRY_CALL reordering FEntryInserter prepends FENTRY_CALL to the first basic block. In case there are other instructions, PostRA Machine Instruction Scheduler can move FENTRY_CALL call around. This actually occurs on SystemZ (see the testcase). This is bad for the following reasons: * FENTRY_CALL clobbers registers. * Linux Kernel depends on whatever FENTRY_CALL expands to to be the very first instruction in the function. Fix by adding isCall attribute to FENTRY_CALL, which prevents reordering by making it a scheduling boundary for PostRA Machine Instruction Scheduler. Reviewed By: niravd Differential Revision: https://reviews.llvm.org/D91218 Added: llvm/test/CodeGen/SystemZ/fentry-debug-info.ll llvm/test/CodeGen/SystemZ/fentry-no-reorder.ll Modified: llvm/include/llvm/Target/Target.td llvm/lib/CodeGen/MachineInstr.cpp Removed: diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 9664f70c7a02..1c97d70a477f 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -1282,6 +1282,7 @@ def FENTRY_CALL : StandardPseudoInstruction { let InOperandList = (ins); let AsmString = "# FEntry call"; let usesCustomInserter = true; + let isCall = true; let mayLoad = true; let mayStore = true; let hasSideEffects = true; diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index fd658cdb41b9..900abd2b260d 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -713,6 +713,7 @@ bool MachineInstr::isCandidateForCallSiteEntry(QueryType Type) const { case TargetOpcode::PATCHPOINT: case TargetOpcode::STACKMAP: case TargetOpcode::STATEPOINT: + case TargetOpcode::FENTRY_CALL: return false; } return true; diff --git a/llvm/test/CodeGen/SystemZ/fentry-debug-info.ll b/llvm/test/CodeGen/SystemZ/fentry-debug-info.ll new file mode 100644 index ..e78c5aad0240 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/fentry-debug-info.ll @@ -0,0 +1,22 @@ +; Test that compiling with fentry and debuginfo works. +; +; RUN: llc %s -mtriple=s390x-linux-gnu -o - -verify-machineinstrs + +define dso_local void @_Z1av() local_unnamed_addr #0 !dbg !7 { +entry: + ret void +} + +attributes #0 = { norecurse nounwind readnone "fentry-call"="true" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "a.cpp", directory: "/tmp") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!7 = distinct !DISubprogram(name: "a", linkageName: "_Z1av", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} diff --git a/llvm/test/CodeGen/SystemZ/fentry-no-reorder.ll b/llvm/test/CodeGen/SystemZ/fentry-no-reorder.ll new file mode 100644 index ..f8a9409ed84e --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/fentry-no-reorder.ll @@ -0,0 +1,19 @@ +; RUN: llc %s -mtriple=s390x-linux-gnu -mcpu=zEC12 -o - -verify-machineinstrs \ +; RUN: | FileCheck %s + +@PawnTT = dso_local local_unnamed_addr global [2048 x i8] zeroinitializer, align 2 + +define dso_local void @clear_pawn_tt() local_unnamed_addr #0 { +entry: + call void @llvm.memset.p0i8.i64(i8* nonnull align 2 dereferenceable(2048) getelementptr inbounds ([2048 x i8], [2048 x i8]* @PawnTT, i64 0, i64 0), i8 0, i64 2048, i1 false) + ret void +} + +declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1 + +attributes #0 = { nofree nounwind writeonly "fentry-call"="true" } +attributes #1 = { argmemonly nofree nosync nounwind willreturn writeonly } + +; CHECK: clear_pawn_tt: # @clear_pawn_tt +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: brasl %r0, __fentry__@PLT ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits