[llvm] 45b8a74 - [LLD][COFF] When using LLD-as-a-library, always prevent re-entrance on failures
Alexandre Ganea via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 12 05:14:55 PST 2020
Author: Alexandre Ganea
Date: 2020-11-12T08:14:43-05:00
New Revision: 45b8a741fbbf271e0fb71294cb7cdce3ad4b9bf3
URL: https://github.com/llvm/llvm-project/commit/45b8a741fbbf271e0fb71294cb7cdce3ad4b9bf3
DIFF: https://github.com/llvm/llvm-project/commit/45b8a741fbbf271e0fb71294cb7cdce3ad4b9bf3.diff
LOG: [LLD][COFF] When using LLD-as-a-library, always prevent re-entrance on failures
This is a follow-up for D70378 (Cover usage of LLD as a library).
While debugging an intermittent failure on a bot, I recalled this scenario which
causes the issue:
1.When executing lld/test/ELF/invalid/symtab-sh-info.s L45, we reach
lld::elf::Obj-File::ObjFile() which goes straight into its base ELFFileBase(),
then ELFFileBase::init().
2.At that point fatal() is thrown in lld/ELF/InputFiles.cpp L381, leaving a
half-initialized ObjFile instance.
3.We then end up in lld::exitLld() and since we are running with LLD_IN_TEST, we
hapily restore the control flow to CrashRecoveryContext::RunSafely() then back
in lld::safeLldMain().
4.Before this patch, we called errorHandler().reset() just after, and this
attempted to reset the associated SpecificAlloc<ObjFile<ELF64LE>>. That tried
to free the half-initialized ObjFile instance, and more precisely its
ObjFile::dwarf member.
Sometimes that worked, sometimes it failed and was catched by the
CrashRecoveryContext. This scenario was the reason we called
errorHandler().reset() through a CrashRecoveryContext.
But in some rare cases, the above repro somehow corrupted the heap, creating a
stack overflow. When the CrashRecoveryContext's filter (that is,
__except (ExceptionFilter(GetExceptionInformation()))) tried to handle the
exception, it crashed again since the stack was exhausted -- and that took the
whole application down. That is the issue seen on the bot. Locally it happens
about 1 times out of 15.
Now this situation can happen anywhere in LLD. Since catching stack overflows is
not a reliable scenario ATM when using CrashRecoveryContext, we're now
preventing further re-entrance when such failures occur, by signaling
lld::SafeReturn::canRunAgain=false. When running with LLD_IN_TEST=2 (or above),
only one iteration will be executed, instead of two.
Differential Revision: https://reviews.llvm.org/D88348
Added:
Modified:
lld/Common/ErrorHandler.cpp
lld/include/lld/Common/Driver.h
lld/test/COFF/arm-thumb-branch20-error.s
lld/test/COFF/comdat-selection.s
lld/test/COFF/delayimports-error.test
lld/test/COFF/driver-windows.test
lld/test/COFF/driver.test
lld/test/COFF/export-limit.s
lld/test/COFF/failifmismatch.test
lld/test/COFF/invalid-obj.test
lld/test/COFF/invalid-section-number.test
lld/test/COFF/linkenv.test
lld/test/COFF/manifestinput-error.test
lld/test/COFF/merge.test
lld/test/COFF/pdata-arm64-bad.yaml
lld/test/COFF/precomp-link.test
lld/test/COFF/thin-archive.s
lld/test/COFF/thunk-replace.s
lld/tools/lld/lld.cpp
llvm/include/llvm/Support/CrashRecoveryContext.h
llvm/include/llvm/Support/Process.h
llvm/lib/Support/CrashRecoveryContext.cpp
llvm/lib/Support/Process.cpp
Removed:
################################################################################
diff --git a/lld/Common/ErrorHandler.cpp b/lld/Common/ErrorHandler.cpp
index 41122e8fb9fd..269a0f62ec65 100644
--- a/lld/Common/ErrorHandler.cpp
+++ b/lld/Common/ErrorHandler.cpp
@@ -64,6 +64,10 @@ void lld::exitLld(int val) {
if (errorHandler().outputBuffer)
errorHandler().outputBuffer->discard();
+ // Re-throw a possible signal or exception once/if it was catched by
+ // safeLldMain().
+ CrashRecoveryContext::throwIfCrash(val);
+
// Dealloc/destroy ManagedStatic variables before calling _exit().
// In an LTO build, allows us to get the output of -time-passes.
// Ensures that the thread pool for the parallel algorithms is stopped to
@@ -76,7 +80,10 @@ void lld::exitLld(int val) {
lld::outs().flush();
lld::errs().flush();
}
- llvm::sys::Process::Exit(val);
+ // When running inside safeLldMain(), restore the control flow back to the
+ // CrashRecoveryContext. Otherwise simply use _exit(), meanning no cleanup,
+ // since we want to avoid further crashes on shutdown.
+ llvm::sys::Process::Exit(val, /*NoCleanup=*/true);
}
void lld::diagnosticHandler(const DiagnosticInfo &di) {
diff --git a/lld/include/lld/Common/Driver.h b/lld/include/lld/Common/Driver.h
index 7a0ad4b364cc..eb5bc7b82b9b 100644
--- a/lld/include/lld/Common/Driver.h
+++ b/lld/include/lld/Common/Driver.h
@@ -21,7 +21,9 @@ struct SafeReturn {
// Generic entry point when using LLD as a library, safe for re-entry, supports
// crash recovery. Returns a general completion code and a boolean telling
// whether it can be called again. In some cases, a crash could corrupt memory
-// and re-entry would not be possible anymore.
+// and re-entry would not be possible anymore. Use exitLld() in that case to
+// properly exit your application and avoid intermittent crashes on exit caused
+// by cleanup.
SafeReturn safeLldMain(int argc, const char **argv, llvm::raw_ostream &stdoutOS,
llvm::raw_ostream &stderrOS);
diff --git a/lld/test/COFF/arm-thumb-branch20-error.s b/lld/test/COFF/arm-thumb-branch20-error.s
index fbbc0d49d02b..6802a02fe970 100644
--- a/lld/test/COFF/arm-thumb-branch20-error.s
+++ b/lld/test/COFF/arm-thumb-branch20-error.s
@@ -1,6 +1,6 @@
// REQUIRES: arm
// RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %s -o %t.obj
-// RUN: not lld-link -entry:_start -subsystem:console %t.obj -out:%t.exe 2>&1 | FileCheck %s
+// RUN: env LLD_IN_TEST=1 not lld-link -entry:_start -subsystem:console %t.obj -out:%t.exe 2>&1 | FileCheck %s
.syntax unified
.globl _start
_start:
diff --git a/lld/test/COFF/comdat-selection.s b/lld/test/COFF/comdat-selection.s
index 988d9bd9516d..a20ee38d0c4a 100644
--- a/lld/test/COFF/comdat-selection.s
+++ b/lld/test/COFF/comdat-selection.s
@@ -32,11 +32,11 @@ symbol:
# RUN: cp %t.same_size.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.same_size.obj %t.obj
# RUN: cp %t.same_contents.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.obj
# RUN: cp %t.largest.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.largest.obj %t.obj
-# RUN: cp %t.newest.obj %t.obj && not lld-link /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEW %s
+# RUN: cp %t.newest.obj %t.obj && env LLD_IN_TEST=1 not lld-link /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEW %s
# NEWNEW: lld-link: error: unknown comdat type 7 for symbol
# /force doesn't affect errors about unknown comdat types.
-# RUN: cp %t.newest.obj %t.obj && not lld-link /force /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEWFORCE %s
+# RUN: cp %t.newest.obj %t.obj && env LLD_IN_TEST=1 not lld-link /force /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEWFORCE %s
# NEWNEWFORCE: lld-link: error: unknown comdat type 7 for symbol
# Check that same_size, same_contents, largest do what they're supposed to.
diff --git a/lld/test/COFF/delayimports-error.test b/lld/test/COFF/delayimports-error.test
index f630103d093f..cced9fb65e61 100644
--- a/lld/test/COFF/delayimports-error.test
+++ b/lld/test/COFF/delayimports-error.test
@@ -3,7 +3,8 @@
# RUN: lld-link /out:%t.dir/foo.dll /dll %t1.obj /export:datasym,DATA /noentry
# RUN: yaml2obj %s -o %t2.obj
-# RUN: not lld-link /out:%t.exe /entry:main %t2.obj %t.dir/foo.lib /delayload:foo.dll \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main %t2.obj \
+# RUN: %t.dir/foo.lib /delayload:foo.dll \
# RUN: /alternatename:__delayLoadHelper2=main /opt:noref >& %t.log
# RUN: FileCheck %s < %t.log
diff --git a/lld/test/COFF/driver-windows.test b/lld/test/COFF/driver-windows.test
index 1b93a53bddb3..407da16359bf 100644
--- a/lld/test/COFF/driver-windows.test
+++ b/lld/test/COFF/driver-windows.test
@@ -1,3 +1,3 @@
# REQUIRES: system-windows
-# RUN: not LLD-LINK 2>&1 | FileCheck %s
+# RUN: env LLD_IN_TEST=1 not LLD-LINK 2>&1 | FileCheck %s
CHECK: no input files
diff --git a/lld/test/COFF/driver.test b/lld/test/COFF/driver.test
index 143d5f74fdba..d756dc9ed4aa 100644
--- a/lld/test/COFF/driver.test
+++ b/lld/test/COFF/driver.test
@@ -13,18 +13,18 @@ BADFILE: bad file type. Did you specify a DLL instead of an import library?
# RUN: lld-link /lib /help | FileCheck -check-prefix=LIBHELP %s
LIBHELP: OVERVIEW: LLVM Lib
-# RUN: not lld-link /WX /lib 2>&1 | FileCheck -check-prefix=LIBBAD %s
+# RUN: env LLD_IN_TEST=1 not lld-link /WX /lib 2>&1 | FileCheck -check-prefix=LIBBAD %s
LIBBAD: ignoring /lib since it's not the first argument
# RUN: yaml2obj %p/Inputs/hello32.yaml -o %t.obj
# RUN: not lld-link /out:/ %t.obj 2>&1 | FileCheck -check-prefix=DIR %s
DIR: cannot open output file
-# RUN: not lld-link -version 2>&1 | FileCheck -check-prefix=SPELLVERSION %s
+# RUN: env LLD_IN_TEST=1 not lld-link -version 2>&1 | FileCheck -check-prefix=SPELLVERSION %s
SPELLVERSION: ignoring unknown argument '-version', did you mean '--version'
SPELLVERSION: no input files
-# RUN: not lld-link -nodefaultlibs 2>&1 | FileCheck -check-prefix=SPELLNODEFAULTLIB %s
+# RUN: env LLD_IN_TEST=1 not lld-link -nodefaultlibs 2>&1 | FileCheck -check-prefix=SPELLNODEFAULTLIB %s
SPELLNODEFAULTLIB: ignoring unknown argument '-nodefaultlibs', did you mean '-nodefaultlib'
SPELLNODEFAULTLIB: no input files
diff --git a/lld/test/COFF/export-limit.s b/lld/test/COFF/export-limit.s
index e65a84cb718f..8936754ab268 100644
--- a/lld/test/COFF/export-limit.s
+++ b/lld/test/COFF/export-limit.s
@@ -3,7 +3,7 @@
# RUN: %python %p/Inputs/def-many.py 65536 > %t-65536.def
# RUN: llvm-mc -triple x86_64-win32 %s -filetype=obj -o %t.obj
# RUN: lld-link -dll -noentry %t.obj -out:%t.dll -def:%t-65535.def
-# RUN: not lld-link -dll -noentry %t.obj -out:%t.dll -def:%t-65536.def 2>&1 | FileCheck %s
+# RUN: env LLD_IN_TEST=1 not lld-link -dll -noentry %t.obj -out:%t.dll -def:%t-65536.def 2>&1 | FileCheck %s
# CHECK: error: too many exported symbols
diff --git a/lld/test/COFF/failifmismatch.test b/lld/test/COFF/failifmismatch.test
index 1cf77e47b035..25ca1012dc0d 100644
--- a/lld/test/COFF/failifmismatch.test
+++ b/lld/test/COFF/failifmismatch.test
@@ -9,15 +9,15 @@ RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k2=v1
RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v1
-RUN: not lld-link /entry:main /subsystem:console /out:%t.exe \
+RUN: env LLD_IN_TEST=1 not lld-link /entry:main /subsystem:console /out:%t.exe \
RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v2 2>&1 | FileCheck %s
RUN: llc < %p/Inputs/failmismatch1.ll -mtriple x86_64-windows-msvc -filetype obj -o %t1.obj
RUN: llc < %p/Inputs/failmismatch2.ll -mtriple x86_64-windows-msvc -filetype obj -o %t2.obj
-RUN: not lld-link %t1.obj %t2.obj 2>&1 | FileCheck %s -check-prefix OBJ
+RUN: env LLD_IN_TEST=1 not lld-link %t1.obj %t2.obj 2>&1 | FileCheck %s -check-prefix OBJ
RUN: llvm-lib %t1.obj /out:%t.lib
-RUN: not lld-link %t.lib %t2.obj 2>&1 | FileCheck %s -check-prefix LIB
+RUN: env LLD_IN_TEST=1 not lld-link %t.lib %t2.obj 2>&1 | FileCheck %s -check-prefix LIB
CHECK: lld-link: error: /failifmismatch: mismatch detected for 'k1':
CHECK-NEXT: >>> cmd-line has value v1
diff --git a/lld/test/COFF/invalid-obj.test b/lld/test/COFF/invalid-obj.test
index d24daa48ddbf..078cd13dad13 100644
--- a/lld/test/COFF/invalid-obj.test
+++ b/lld/test/COFF/invalid-obj.test
@@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t.obj
-# RUN: not lld-link %t.obj 2>&1 | FileCheck %s
+# RUN: env LLD_IN_TEST=1 not lld-link %t.obj 2>&1 | FileCheck %s
# CHECK: getSectionName failed: #1:
diff --git a/lld/test/COFF/invalid-section-number.test b/lld/test/COFF/invalid-section-number.test
index 432d3549bb16..8860affaaa5c 100644
--- a/lld/test/COFF/invalid-section-number.test
+++ b/lld/test/COFF/invalid-section-number.test
@@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t.obj
-# RUN: not lld-link %t.obj 2>&1 | FileCheck %s
+# RUN: env LLD_IN_TEST=1 not lld-link %t.obj 2>&1 | FileCheck %s
# CHECK: foo should not refer to special section -10
diff --git a/lld/test/COFF/linkenv.test b/lld/test/COFF/linkenv.test
index 78d11fd5d0a8..752f39f12631 100644
--- a/lld/test/COFF/linkenv.test
+++ b/lld/test/COFF/linkenv.test
@@ -3,7 +3,7 @@
CHECK: OVERVIEW: LLVM Linker
-# RUN: env LINK=-help not lld-link /lldignoreenv 2>&1 | \
+# RUN: env LLD_IN_TEST=1 LINK=-help not lld-link /lldignoreenv 2>&1 | \
# RUN: FileCheck --check-prefix=ERR %s
ERR: error: no input files
diff --git a/lld/test/COFF/manifestinput-error.test b/lld/test/COFF/manifestinput-error.test
index 9d47b9c9a79e..ea61bae2f7c0 100644
--- a/lld/test/COFF/manifestinput-error.test
+++ b/lld/test/COFF/manifestinput-error.test
@@ -2,7 +2,7 @@
# UNSUPPORTED: libxml2
# RUN: yaml2obj %p/Inputs/ret42.yaml -o %t.obj
-# RUN: not lld-link /out:%t.exe /entry:main \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main \
# RUN: /manifest:embed \
# RUN: /manifestuac:"level='requireAdministrator'" \
# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj 2>&1 | FileCheck %s
diff --git a/lld/test/COFF/merge.test b/lld/test/COFF/merge.test
index af368407e7e8..11824aac1b08 100644
--- a/lld/test/COFF/merge.test
+++ b/lld/test/COFF/merge.test
@@ -7,17 +7,17 @@
# RUN: /merge:.foo=.bar /merge:.bar=.abc %t.obj /debug
# RUN: llvm-readobj --sections %t.exe | FileCheck --check-prefix=CHECK2 %s
-# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main /subsystem:console /force \
# RUN: /merge:.rsrc=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RSRC %s
-# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main /subsystem:console /force \
# RUN: /merge:.foo=.rsrc %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RSRC %s
-# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main /subsystem:console /force \
# RUN: /merge:.reloc=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RELOC %s
-# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main /subsystem:console /force \
# RUN: /merge:.foo=.reloc %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RELOC %s
-# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main /subsystem:console /force \
# RUN: /merge:.foo=.foo1 /merge:.foo1=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-CYCLE %s
-# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:main /subsystem:console /force \
# RUN: /merge:.foo=.foo1 /merge:.foo1=.foo2 /merge:.foo2=.foo1 %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-CYCLE %s
# CHECK: Name: .def
diff --git a/lld/test/COFF/pdata-arm64-bad.yaml b/lld/test/COFF/pdata-arm64-bad.yaml
index 8b43b66cc7ce..1314998aef90 100644
--- a/lld/test/COFF/pdata-arm64-bad.yaml
+++ b/lld/test/COFF/pdata-arm64-bad.yaml
@@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t.obj
-# RUN: not lld-link /out:%t.exe /entry:func1 /subsystem:console %t.obj 2>&1 | FileCheck %s
+# RUN: env LLD_IN_TEST=1 not lld-link /out:%t.exe /entry:func1 /subsystem:console %t.obj 2>&1 | FileCheck %s
# This file is like pdata-arm64.yaml, except that .pdata has been extended with
# 4 bytes. This can happen due to for example bad assembler input. Check that
diff --git a/lld/test/COFF/precomp-link.test b/lld/test/COFF/precomp-link.test
index c9a5c605da8f..ee496c9bc946 100644
--- a/lld/test/COFF/precomp-link.test
+++ b/lld/test/COFF/precomp-link.test
@@ -33,9 +33,9 @@ RUN: sed 's/Signature: *545589255/Signature: 0/' < %t.precomp.yaml > precomp-zer
RUN: yaml2obj precomp-no-objname.yaml -o %t.precomp-no-objname.obj
RUN: yaml2obj precomp-zero-sig.yaml -o %t.precomp-zero-sig.obj
-RUN: not lld-link %t.precomp-no-objname.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-NO-SIGNATURE
+RUN: env LLD_IN_TEST=1 not lld-link %t.precomp-no-objname.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-NO-SIGNATURE
-RUN: not lld-link %t.precomp-zero-sig.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-NO-SIGNATURE
+RUN: env LLD_IN_TEST=1 not lld-link %t.precomp-zero-sig.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-NO-SIGNATURE
FAILURE-NO-SIGNATURE: error: {{.*}}.obj claims to be a PCH object, but does not have a valid signature
@@ -43,7 +43,7 @@ Check that two PCH objs with duplicate signatures are an error.
RUN: cp %S/Inputs/precomp.obj %t.precomp-dup.obj
-RUN: not lld-link %S/Inputs/precomp.obj %t.precomp-dup.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-DUP-SIGNATURE
+RUN: env LLD_IN_TEST=1 not lld-link %S/Inputs/precomp.obj %t.precomp-dup.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-DUP-SIGNATURE
FAILURE-DUP-SIGNATURE: error: a PCH object with the same signature has already been provided ({{.*precomp.obj and .*precomp-dup.obj.*}})
diff --git a/lld/test/COFF/thin-archive.s b/lld/test/COFF/thin-archive.s
index a1491cb7c4ab..a35eabed688c 100644
--- a/lld/test/COFF/thin-archive.s
+++ b/lld/test/COFF/thin-archive.s
@@ -17,9 +17,9 @@
# RUN: rm %t.lib.obj
# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \
# RUN: FileCheck --allow-empty %s
-# RUN: not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \
-# RUN: FileCheck --check-prefix=NOOBJ %s
-# RUN: not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe \
+# RUN: env LLD_IN_TEST=1 not lld-link /entry:main %t.main.obj %t_thin.lib \
+# RUN: /out:%t.exe 2>&1 | FileCheck --check-prefix=NOOBJ %s
+# RUN: env LLD_IN_TEST=1 not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe \
# RUN: /demangle:no 2>&1 | FileCheck --check-prefix=NOOBJNODEMANGLE %s
# CHECK-NOT: error: could not get the buffer for the member defining
diff --git a/lld/test/COFF/thunk-replace.s b/lld/test/COFF/thunk-replace.s
index 2d47fcc64837..0b53f09ef048 100644
--- a/lld/test/COFF/thunk-replace.s
+++ b/lld/test/COFF/thunk-replace.s
@@ -3,7 +3,8 @@
# RUN: llvm-mc -triple=x86_64-win32 %s -filetype=obj -o %t.main.obj
# RUN: llvm-mc -triple=x86_64-win32 %p/Inputs/otherFunc.s -filetype=obj -o %t.other.obj
# RUN: llvm-ar rcs %t.other.lib %t.other.obj
-# RUN: not lld-link -out:%t.exe -entry:main %t.main.obj %p/Inputs/std64.lib %t.other.lib -opt:noref 2>&1 | FileCheck %s
+# RUN: env LLD_IN_TEST=1 not lld-link -out:%t.exe -entry:main %t.main.obj \
+# RUN: %p/Inputs/std64.lib %t.other.lib -opt:noref 2>&1 | FileCheck %s
# CHECK: MessageBoxA was replaced
.global main
diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp
index 48d5ae1a0ea0..5d71a8f24adf 100644
--- a/lld/tools/lld/lld.cpp
+++ b/lld/tools/lld/lld.cpp
@@ -179,7 +179,7 @@ SafeReturn lld::safeLldMain(int argc, const char **argv,
if (!crc.RunSafely([&]() {
r = lldMain(argc, argv, stdoutOS, stderrOS, /*exitEarly=*/false);
}))
- r = crc.RetCode;
+ return {crc.RetCode, /*canRunAgain=*/false};
}
// Cleanup memory and reset everything back in pristine condition. This path
@@ -221,7 +221,7 @@ int main(int argc, const char **argv) {
// Execute one iteration.
auto r = safeLldMain(argc, argv, llvm::outs(), llvm::errs());
if (!r.canRunAgain)
- _exit(r.ret); // Exit now, can't re-execute again.
+ exitLld(r.ret); // Exit now, can't re-execute again.
if (!mainRet) {
mainRet = r.ret;
@@ -230,14 +230,5 @@ int main(int argc, const char **argv) {
return r.ret;
}
}
-#if LLVM_ON_UNIX
- // Re-throw the signal so it can be caught by WIFSIGNALED in
- // llvm/lib/Support/Unix/Program.inc. This is required to correctly handle
- // usages of `not --crash`.
- if (*mainRet > 128) {
- llvm::sys::unregisterHandlers();
- raise(*mainRet - 128);
- }
-#endif
return *mainRet;
}
diff --git a/llvm/include/llvm/Support/CrashRecoveryContext.h b/llvm/include/llvm/Support/CrashRecoveryContext.h
index 0fd1d4675c7c..f756635ee1f9 100644
--- a/llvm/include/llvm/Support/CrashRecoveryContext.h
+++ b/llvm/include/llvm/Support/CrashRecoveryContext.h
@@ -102,6 +102,10 @@ class CrashRecoveryContext {
LLVM_ATTRIBUTE_NORETURN
void HandleExit(int RetCode);
+ /// Throw again a signal or an exception, after it was catched once by a
+ /// CrashRecoveryContext.
+ static bool throwIfCrash(int RetCode);
+
/// In case of a crash, this is the crash identifier.
int RetCode = 0;
diff --git a/llvm/include/llvm/Support/Process.h b/llvm/include/llvm/Support/Process.h
index af5091ab8ff4..729917bb41f4 100644
--- a/llvm/include/llvm/Support/Process.h
+++ b/llvm/include/llvm/Support/Process.h
@@ -213,8 +213,9 @@ class Process {
/// Equivalent to ::exit(), except when running inside a CrashRecoveryContext.
/// In that case, the control flow will resume after RunSafely(), like for a
/// crash, rather than exiting the current process.
+ /// Use \arg NoCleanup for calling _exit() instead of exit().
LLVM_ATTRIBUTE_NORETURN
- static void Exit(int RetCode);
+ static void Exit(int RetCode, bool NoCleanup = false);
};
}
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index 7609f04cf68c..77f00189274f 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -442,6 +442,26 @@ void CrashRecoveryContext::HandleExit(int RetCode) {
llvm_unreachable("Most likely setjmp wasn't called!");
}
+bool CrashRecoveryContext::throwIfCrash(int RetCode) {
+#if defined(_WIN32)
+ // On Windows, the high bits are reserved for kernel return codes. Values
+ // starting with 0x80000000 are reserved for "warnings"; values of 0xC0000000
+ // and up are for "errors". In practice, both are interpreted as a
+ // non-continuable signal.
+ unsigned Code = ((unsigned)RetCode & 0xF0000000) >> 28;
+ if (Code != 0xC && Code != 8)
+ return false;
+ ::RaiseException(RetCode, 0, 0, NULL);
+#else
+ // On Unix, signals are represented by return codes of 128 or higher.
+ if (RetCode <= 128)
+ return false;
+ llvm::sys::unregisterHandlers();
+ raise(RetCode - 128);
+#endif
+ return true;
+}
+
// FIXME: Portability.
static void setThreadBackgroundPriority() {
#ifdef __APPLE__
diff --git a/llvm/lib/Support/Process.cpp b/llvm/lib/Support/Process.cpp
index 9f0b689ce6c8..8626117f2a0b 100644
--- a/llvm/lib/Support/Process.cpp
+++ b/llvm/lib/Support/Process.cpp
@@ -20,6 +20,8 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
+#include <stddef.h> // for _Exit
+
using namespace llvm;
using namespace sys;
@@ -91,10 +93,14 @@ static bool coreFilesPrevented = !LLVM_ENABLE_CRASH_DUMPS;
bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; }
LLVM_ATTRIBUTE_NORETURN
-void Process::Exit(int RetCode) {
+void Process::Exit(int RetCode, bool NoCleanup) {
if (CrashRecoveryContext *CRC = CrashRecoveryContext::GetCurrent())
CRC->HandleExit(RetCode);
- ::exit(RetCode);
+
+ if (NoCleanup)
+ _Exit(RetCode);
+ else
+ ::exit(RetCode);
}
// Include the platform-specific parts of this class.
More information about the llvm-commits
mailing list