HardenedBSD/src 5ce9407 — . UPDATING, cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/syscall tst.args.c
Merge branch 'freebsd/current/master' into hardened/current/master * freebsd/current/master: (48 commits) Ensure that we use a 64-bit value for the last mmap() argument. This is an additional and hopefully final fix for bug report 230962. This bug was introduced with the change to use softdep_bp_to_mp() in January 2018 changes -r327723 and -r327821. The softdep_bp_to_mp() function failed to include VSOCK as one of the valid cases. Build common kernel dependencies before modules. Rename fuse(4) to fusefs(4) Pull in r352826 from upstream lld trunk (by Fangrui Song): Use -fdebug-prefix-map to map auto-generated kernel build paths. Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp 8.0.0 final release r356365. There were no functional changes since the most recent merge, of 8.0.0 rc5. googletest: backport GTEST_SKIP to googletest 1.8.1 fuse(4): fix a race condition in the tests fuse(4): remove more debugging printfs fuse(4): build the tests with the new googletest in base fuse(4): add tests for some mount options. fuse(4): add tests for the FOPEN_KEEP_CACHE option fuse(4): add tests for the FUSE_ASYNC_READ option VOP_INACTIVE(9): clarify wording fuse(4): add tests for ENOSYS special cases fuse(4): combine common code in the tests fuse(4): add some miscellaneous test cases that I had overlooked fuse(4): add tests for FUSE_DESTROY, FUSE_FORGET, and unlinking open files fuse(4): add tests for extended attributes ...
@@ -31,6 +31,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW: | |||
disable the most expensive debugging functionality run | disable the most expensive debugging functionality run | ||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".) | "ln -s 'abort:false,junk:false' /etc/malloc.conf".) | ||
+20190320: | |||
+ The fuse(4) module has been renamed to fusefs(4) for consistency with | |||
+ other filesystems. You should update any kld_load="fuse" entries in | |||
+ /etc/rc.conf, fuse_load="YES" entries in /boot/loader.conf, and | |||
+ "options FUSE" enties in kernel config files. | |||
+ | |||
20190304: | 20190304: | ||
Clang, llvm, lld, lldb, compiler-rt and libc++ have been upgraded to | Clang, llvm, lld, lldb, compiler-rt and libc++ have been upgraded to | ||
8.0.0. Please see the 20141231 entry below for information about | 8.0.0. Please see the 20141231 entry below for information about |
@@ -35,7 +35,8 @@ int | |||
main(int argc, char **argv) | main(int argc, char **argv) | ||
{ | { | ||
for (;;) { | for (;;) { | ||
- (void) __syscall(SYS_mmap, NULL, 1, 2, 3, -1, | + (void) __syscall(SYS_mmap, NULL, (size_t)1, 2, 3, -1, | ||
+ (off_t)0x12345678); | |||
} | } | ||
return (0); | return (0); |
@@ -217,6 +217,7 @@ if (gtest_build_tes | |||
test/gtest-typed-test2_test.cc) | test/gtest-typed-test2_test.cc) | ||
cxx_test(gtest_unittest gtest_main) | cxx_test(gtest_unittest gtest_main) | ||
cxx_test(gtest-unittest-api_test gtest) | cxx_test(gtest-unittest-api_test gtest) | ||
+ cxx_test(gtest_skip_test gtest_main) | |||
############################################################ | ############################################################ | ||
# C++ tests built with non-standard compiler flags. | # C++ tests built with non-standard compiler flags. |
@@ -53,7 +53,8 @@ class GTEST_API_ TestPartResult { | |||
enum Type { | enum Type { | ||
kSuccess, // Succeeded. | kSuccess, // Succeeded. | ||
kNonFatalFailure | kNonFatalFailure | ||
- kFatalFailure | + kFatalFailure, // Failed and the test should be terminated. | ||
+ kSkip // Skipped. | |||
}; | }; | ||
// C'tor. TestPartResult does NOT have a default constructor. | // C'tor. TestPartResult does NOT have a default constructor. | ||
@@ -89,18 +90,21 @@ class GTEST_API_ TestPartResult { | |||
// Gets the message associated with the test part. | // Gets the message associated with the test part. | ||
const char* message() const { return message_.c_str(); } | const char* message() const { return message_.c_str(); } | ||
+ // Returns true iff the test part was skipped. | |||
+ bool skipped() const { return type_ == kSkip; } | |||
+ | |||
// Returns true iff the test part passed. | // Returns true iff the test part passed. | ||
bool passed() const { return type_ == kSuccess; } | bool passed() const { return type_ == kSuccess; } | ||
- // Returns true iff the test part failed. | |||
- bool failed() const { return type_ != kSuccess; } | |||
- | |||
// Returns true iff the test part non-fatally failed. | // Returns true iff the test part non-fatally failed. | ||
bool nonfatally_faile | bool nonfatally_faile | ||
// Returns true iff the test part fatally failed. | // Returns true iff the test part fatally failed. | ||
bool fatally_failed() const { return type_ == kFatalFailure; } | bool fatally_failed() const { return type_ == kFatalFailure; } | ||
+ // Returns true iff the test part failed. | |||
+ bool failed() const { return fatally_failed() || nonfatally_faile | |||
+ | |||
private: | private: | ||
Type type_; | Type type_; | ||
@@ -440,6 +440,9 @@ class GTEST_API_ Test { | |||
// Returns true iff the current test has a non-fatal failure. | // Returns true iff the current test has a non-fatal failure. | ||
static bool HasNonfatalFailu | static bool HasNonfatalFailu | ||
+ // Returns true iff the current test was skipped. | |||
+ static bool IsSkipped(); | |||
+ | |||
// Returns true iff the current test has a (either fatal or | // Returns true iff the current test has a (either fatal or | ||
// non-fatal) failure. | // non-fatal) failure. | ||
static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailu | static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailu | ||
@@ -574,7 +577,10 @@ class GTEST_API_ TestResult { | |||
int test_property_co | int test_property_co | ||
// Returns true iff the test passed (i.e. no test part failed). | // Returns true iff the test passed (i.e. no test part failed). | ||
- bool Passed() const { return !Failed(); } | + bool Passed() const { return !Skipped() && !Failed(); } | ||
+ | |||
+ // Returns true iff the test was skipped. | |||
+ bool Skipped() const; | |||
// Returns true iff the test failed. | // Returns true iff the test failed. | ||
bool Failed() const; | bool Failed() const; | ||
@@ -854,6 +860,9 @@ class GTEST_API_ TestCase { | |||
// Gets the number of successful tests in this test case. | // Gets the number of successful tests in this test case. | ||
int successful_test_ | int successful_test_ | ||
+ // Gets the number of skipped tests in this test case. | |||
+ int skipped_test_cou | |||
+ | |||
// Gets the number of failed tests in this test case. | // Gets the number of failed tests in this test case. | ||
int failed_test_coun | int failed_test_coun | ||
@@ -936,6 +945,11 @@ class GTEST_API_ TestCase { | |||
return test_info->should_run() && test_info->result()->Passed(); | return test_info->should_run() && test_info->result()->Passed(); | ||
} | } | ||
+ // Returns true iff test skipped. | |||
+ static bool TestSkipped(const TestInfo* test_info) { | |||
+ return test_info->should_run() && test_info->result()->Skipped(); | |||
+ } | |||
+ | |||
// Returns true iff test failed. | // Returns true iff test failed. | ||
static bool TestFailed(const TestInfo* test_info) { | static bool TestFailed(const TestInfo* test_info) { | ||
return test_info->should_run() && test_info->result()->Failed(); | return test_info->should_run() && test_info->result()->Failed(); | ||
@@ -1258,6 +1272,9 @@ class GTEST_API_ UnitTest { | |||
// Gets the number of successful tests. | // Gets the number of successful tests. | ||
int successful_test_ | int successful_test_ | ||
+ // Gets the number of skipped tests. | |||
+ int skipped_test_cou | |||
+ | |||
// Gets the number of failed tests. | // Gets the number of failed tests. | ||
int failed_test_coun | int failed_test_coun | ||
@@ -1835,6 +1852,11 @@ class TestWithParam : public Test, public WithParamInterfa | |||
// Macros for indicating success/failure in test code. | // Macros for indicating success/failure in test code. | ||
+// Skips test in runtime. | |||
+// Skipping test aborts current function. | |||
+// Skipped tests are neither successful nor failed. | |||
+#define GTEST_SKIP() GTEST_SKIP_("Skipped") | |||
+ | |||
// ADD_FAILURE unconditionally adds a failure to the current test. | // ADD_FAILURE unconditionally adds a failure to the current test. | ||
// SUCCEED generates a success - it doesn't automatically make the | // SUCCEED generates a success - it doesn't automatically make the | ||
// current test successful, as a test is only successful when it has | // current test successful, as a test is only successful when it has |
@@ -1208,7 +1208,10 @@ class NativeArray { | |||
#define GTEST_SUCCESS_(message) \ | #define GTEST_SUCCESS_(message) \ | ||
GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) | GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) | ||
-// Suppress MSVC warning 4702 (unreachable code) for the code following | +#define GTEST_SKIP_(message) \ | ||
+ return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip) | |||
+ | |||
+// Suppress MSVC warning 4072 (unreachable code) for the code following | |||
// statement if it returns or throws (or doesn't return or throw in some | // statement if it returns or throws (or doesn't return or throw in some | ||
// situations). | // situations). | ||
#define GTEST_SUPPRESS_U | #define GTEST_SUPPRESS_U |
@@ -544,6 +544,9 @@ class GTEST_API_ UnitTestImpl { | |||
// Gets the number of successful tests. | // Gets the number of successful tests. | ||
int successful_test_ | int successful_test_ | ||
+ // Gets the number of skipped tests. | |||
+ int skipped_test_cou | |||
+ | |||
// Gets the number of failed tests. | // Gets the number of failed tests. | ||
int failed_test_coun | int failed_test_coun | ||
@@ -47,12 +47,16 @@ std::string TestPartResult:: | |||
// Prints a TestPartResult object. | // Prints a TestPartResult object. | ||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { | std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { | ||
- return os | + return os << result.file_name() << ":" << result.line_number() << ": " | ||
- << result.file_name() << ":" << result.line_number() << ": " | + << (result.type() == TestPartResult::kSuccess | ||
- << (result.type() == TestPartResult::kSuccess ? "Success" : | + ? "Success" | ||
- result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : | + : result.type() == TestPartResult::kSkip | ||
- "Non-fatal failure") << ":\n" | + ? "Skipped" | ||
- << result.message() << std::endl; | + : result.type() == TestPartResult::kFatalFailure | ||
+ ? "Fatal failure" | |||
+ : "Non-fatal failure") | |||
+ << ":\n" | |||
+ << result.message() << std::endl; | |||
} | } | ||
// Appends a TestPartResult to the array. | // Appends a TestPartResult to the array. |
@@ -796,6 +796,11 @@ int UnitTestImpl::su | |||
return SumOverTestCaseL | return SumOverTestCaseL | ||
} | } | ||
+// Gets the number of skipped tests. | |||
+int UnitTestImpl::skipped_test_cou | |||
+ return SumOverTestCaseL | |||
+} | |||
+ | |||
// Gets the number of failed tests. | // Gets the number of failed tests. | ||
int UnitTestImpl::failed_test_coun | int UnitTestImpl::failed_test_coun | ||
return SumOverTestCaseL | return SumOverTestCaseL | ||
@@ -2207,6 +2212,16 @@ void TestResult::Clea | |||
elapsed_time_ = 0; | elapsed_time_ = 0; | ||
} | } | ||
+// Returns true off the test part was skipped. | |||
+static bool TestPartSkipped(const TestPartResult& result) { | |||
+ return result.skipped(); | |||
+} | |||
+ | |||
+// Returns true iff the test was skipped. | |||
+bool TestResult::Skipped() const { | |||
+ return !Failed() && CountIf(test_part_result | |||
+} | |||
+ | |||
// Returns true iff the test failed. | // Returns true iff the test failed. | ||
bool TestResult::Failed() const { | bool TestResult::Failed() const { | ||
for (int i = 0; i < total_part_count | for (int i = 0; i < total_part_count | ||
@@ -2511,8 +2526,9 @@ void Test::Run() { | |||
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); | internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); | ||
impl->os_stack_trace_g | impl->os_stack_trace_g | ||
internal::HandleExceptions | internal::HandleExceptions | ||
- // We will run the test only if SetUp() was successful | + // We will run the test only if SetUp() was successful and didn't call | ||
- if (!HasFatalFailure()) { | + // GTEST_SKIP(). | ||
+ if (!HasFatalFailure() && !IsSkipped()) { | |||
impl->os_stack_trace_g | impl->os_stack_trace_g | ||
internal::HandleExceptions | internal::HandleExceptions | ||
this, &Test::TestBody, "the test body"); | this, &Test::TestBody, "the test body"); | ||
@@ -2537,6 +2553,11 @@ bool Test::HasNonfata | |||
HasNonfatalFailu | HasNonfatalFailu | ||
} | } | ||
+// Returns true iff the current test was skipped. | |||
+bool Test::IsSkipped() { | |||
+ return internal::GetUnitTestImpl()->current_test_res | |||
+} | |||
+ | |||
// class TestInfo | // class TestInfo | ||
// Constructs a TestInfo object. It assumes ownership of the test factory | // Constructs a TestInfo object. It assumes ownership of the test factory | ||
@@ -2685,9 +2706,10 @@ void TestInfo::Run() { | |||
factory_, &internal::TestFactoryBase::CreateTest, | factory_, &internal::TestFactoryBase::CreateTest, | ||
"the test fixture's constructor"); | "the test fixture's constructor"); | ||
- // Runs the test if the constructor didn't generate a fatal failure | + // Runs the test if the constructor didn't generate a fatal failure or invoke | ||
+ // GTEST_SKIP(). | |||
// Note that the object will not be null | // Note that the object will not be null | ||
- if (!Test::HasFatalFailure()) { | + if (!Test::HasFatalFailure() && !Test::IsSkipped()) { | ||
// This doesn't throw as all user code that can throw are wrapped into | // This doesn't throw as all user code that can throw are wrapped into | ||
// exception handling code. | // exception handling code. | ||
test->Run(); | test->Run(); | ||
@@ -2715,6 +2737,11 @@ int TestCase::succes | |||
return CountIf(test_info_list_, | return CountIf(test_info_list_, | ||
} | } | ||
+// Gets the number of successful tests in this test case. | |||
+int TestCase::skipped_test_cou | |||
+ return CountIf(test_info_list_, | |||
+} | |||
+ | |||
// Gets the number of failed tests in this test case. | // Gets the number of failed tests in this test case. | ||
int TestCase::failed_test_coun | int TestCase::failed_test_coun | ||
return CountIf(test_info_list_, | return CountIf(test_info_list_, | ||
@@ -2866,6 +2893,8 @@ static std::string FormatTestCaseCo | |||
// between the two when viewing the test result. | // between the two when viewing the test result. | ||
static const char * TestPartResultTy | static const char * TestPartResultTy | ||
switch (type) { | switch (type) { | ||
+ case TestPartResult::kSkip: | |||
+ return "Skipped"; | |||
case TestPartResult::kSuccess: | case TestPartResult::kSuccess: | ||
return "Success"; | return "Success"; | ||
@@ -3119,6 +3148,7 @@ class PrettyUnitTestRe | |||
private: | private: | ||
static void PrintFailedTests | static void PrintFailedTests | ||
+ static void PrintSkippedTest | |||
}; | }; | ||
// Fired before each iteration of tests starts. | // Fired before each iteration of tests starts. | ||
@@ -3187,18 +3217,25 @@ void PrettyUnitTestRe | |||
// Called after an assertion failure. | // Called after an assertion failure. | ||
void PrettyUnitTestRe | void PrettyUnitTestRe | ||
const TestPartResult& result) { | const TestPartResult& result) { | ||
- // If the test part succeeded, we don't need to do anything. | + switch (result.type()) { | ||
- if (result.type() == TestPartResult::kSuccess) | + // If the test part succeeded, or was skipped, | ||
- return; | + // we don't need to do anything. | ||
- | + case TestPartResult::kSkip: | ||
- // Print failure message from the assertion (e.g. expected this and got that). | + case TestPartResult::kSuccess: | ||
- PrintTestPartRes | + return; | ||
- fflush(stdout); | + default: | ||
+ // Print failure message from the assertion | |||
+ // (e.g. expected this and got that). | |||
+ PrintTestPartRes | |||
+ fflush(stdout); | |||
+ } | |||
} | } | ||
void PrettyUnitTestRe | void PrettyUnitTestRe | ||
if (test_info.result()->Passed()) { | if (test_info.result()->Passed()) { | ||
ColoredPrintf(COLOR_GREEN, "[ OK ] "); | ColoredPrintf(COLOR_GREEN, "[ OK ] "); | ||
+ } else if (test_info.result()->Skipped()) { | |||
+ ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); | |||
} else { | } else { | ||
ColoredPrintf(COLOR_RED, "[ FAILED ] "); | ColoredPrintf(COLOR_RED, "[ FAILED ] "); | ||
} | } | ||
@@ -3248,7 +3285,7 @@ void PrettyUnitTestRe | |||
} | } | ||
for (int j = 0; j < test_case.total_test_count | for (int j = 0; j < test_case.total_test_count | ||
const TestInfo& test_info = *test_case.GetTestInfo(j); | const TestInfo& test_info = *test_case.GetTestInfo(j); | ||
- if (!test_info.should_run() || | + if (!test_info.should_run() || !test_info.result()->Failed()) { | ||
continue; | continue; | ||
} | } | ||
ColoredPrintf(COLOR_RED, "[ FAILED ] "); | ColoredPrintf(COLOR_RED, "[ FAILED ] "); | ||
@@ -3259,6 +3296,30 @@ void PrettyUnitTestRe | |||
} | } | ||
} | } | ||
+// Internal helper for printing the list of skipped tests. | |||
+void PrettyUnitTestRe | |||
+ const int skipped_test_cou | |||
+ if (skipped_test_cou | |||
+ return; | |||
+ } | |||
+ | |||
+ for (int i = 0; i < unit_test.total_test_case_ | |||
+ const TestCase& test_case = *unit_test.GetTestCase(i); | |||
+ if (!test_case.should_run() || (test_case.skipped_test_cou | |||
+ continue; | |||
+ } | |||
+ for (int j = 0; j < test_case.total_test_count | |||
+ const TestInfo& test_info = *test_case.GetTestInfo(j); | |||
+ if (!test_info.should_run() || !test_info.result()->Skipped()) { | |||
+ continue; | |||
+ } | |||
+ ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); | |||
+ printf("%s.%s", test_case.name(), test_info.name()); | |||
+ printf("\n"); | |||
+ } | |||
+ } | |||
+} | |||
+ | |||
void PrettyUnitTestRe | void PrettyUnitTestRe | ||
int /*iteration*/) { | int /*iteration*/) { | ||
ColoredPrintf(COLOR_GREEN, "[==========] "); | ColoredPrintf(COLOR_GREEN, "[==========] "); | ||
@@ -3273,6 +3334,13 @@ void PrettyUnitTestRe | |||
ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); | ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); | ||
printf("%s.\n", FormatTestCount(unit_test.successful_test_ | printf("%s.\n", FormatTestCount(unit_test.successful_test_ | ||
+ const int skipped_test_cou | |||
+ if (skipped_test_cou | |||
+ ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); | |||
+ printf("%s, listed below:\n", FormatTestCount(skipped_test_cou | |||
+ PrintSkippedTest | |||
+ } | |||
+ | |||
int num_failures = unit_test.failed_test_coun | int num_failures = unit_test.failed_test_coun | ||
if (!unit_test.Passed()) { | if (!unit_test.Passed()) { | ||
const int failed_test_coun | const int failed_test_coun | ||
@@ -4540,6 +4608,11 @@ int UnitTest::succes | |||
return impl()->successful_test_ | return impl()->successful_test_ | ||
} | } | ||
+// Gets the number of skipped tests. | |||
+int UnitTest::skipped_test_cou | |||
+ return impl()->skipped_test_cou | |||
+} | |||
+ | |||
// Gets the number of failed tests. | // Gets the number of failed tests. | ||
int UnitTest::failed_test_coun | int UnitTest::failed_test_coun | ||
@@ -4660,7 +4733,8 @@ void UnitTest::AddTes | |||
impl_->GetTestPartResul | impl_->GetTestPartResul | ||
ReportTestPartRe | ReportTestPartRe | ||
- if (result_type != TestPartResult::kSuccess | + if (result_type != TestPartResult::kSuccess && | ||
+ result_type != TestPartResult::kSkip) { | |||
// gtest_break_on_f | // gtest_break_on_f | ||
// gtest_throw_on_f | // gtest_throw_on_f | ||
// in the code (perhaps in order to use Google Test assertions | // in the code (perhaps in order to use Google Test assertions |
@@ -46,9 +46,10 @@ class TestPartResultTe | |||
TestPartResultTe | TestPartResultTe | ||
: r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"), | : r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"), | ||
r2_(TestPartResult::kNonFatalFailure | r2_(TestPartResult::kNonFatalFailure | ||
- r3_(TestPartResult::kFatalFailure, | + r3_(TestPartResult::kFatalFailure, nullptr, -1, "Failure!"), | ||
+ r4_(TestPartResult::kSkip, "foo/bar.cc", 2, "Skipped!") {} | |||
- TestPartResult r1_, r2_, | + TestPartResult r1_, r2_, r3_, r4_; | ||
}; | }; | ||
@@ -79,6 +80,7 @@ TEST_F(TestPartR | |||
EXPECT_FALSE(success.failed()); | EXPECT_FALSE(success.failed()); | ||
EXPECT_FALSE(success.nonfatally_faile | EXPECT_FALSE(success.nonfatally_faile | ||
EXPECT_FALSE(success.fatally_failed()); | EXPECT_FALSE(success.fatally_failed()); | ||
+ EXPECT_FALSE(success.skipped()); | |||
const TestPartResult nonfatal_failure | const TestPartResult nonfatal_failure | ||
"file.cc", | "file.cc", | ||
@@ -88,6 +90,7 @@ TEST_F(TestPartR | |||
EXPECT_TRUE(nonfatal_failure | EXPECT_TRUE(nonfatal_failure | ||
EXPECT_TRUE(nonfatal_failure | EXPECT_TRUE(nonfatal_failure | ||
EXPECT_FALSE(nonfatal_failure | EXPECT_FALSE(nonfatal_failure | ||
+ EXPECT_FALSE(nonfatal_failure | |||
const TestPartResult fatal_failure(TestPartResult::kFatalFailure, | const TestPartResult fatal_failure(TestPartResult::kFatalFailure, | ||
"file.cc", | "file.cc", | ||
@@ -97,6 +100,14 @@ TEST_F(TestPartR | |||
EXPECT_TRUE(fatal_failure.failed()); | EXPECT_TRUE(fatal_failure.failed()); | ||
EXPECT_FALSE(fatal_failure.nonfatally_faile | EXPECT_FALSE(fatal_failure.nonfatally_faile | ||
EXPECT_TRUE(fatal_failure.fatally_failed()); | EXPECT_TRUE(fatal_failure.fatally_failed()); | ||
+ EXPECT_FALSE(fatal_failure.skipped()); | |||
+ | |||
+ const TestPartResult skip(TestPartResult::kSkip, "file.cc", 42, "message"); | |||
+ EXPECT_FALSE(skip.passed()); | |||
+ EXPECT_FALSE(skip.failed()); | |||
+ EXPECT_FALSE(skip.nonfatally_faile | |||
+ EXPECT_FALSE(skip.fatally_failed()); | |||
+ EXPECT_TRUE(skip.skipped()); | |||
} | } | ||
// Tests TestPartResult::type(). | // Tests TestPartResult::type(). | ||
@@ -104,23 +115,27 @@ TEST_F(TestPartR | |||
EXPECT_EQ(TestPartResult::kSuccess, r1_.type()); | EXPECT_EQ(TestPartResult::kSuccess, r1_.type()); | ||
EXPECT_EQ(TestPartResult::kNonFatalFailure | EXPECT_EQ(TestPartResult::kNonFatalFailure | ||
EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type()); | EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type()); | ||
+ EXPECT_EQ(TestPartResult::kSkip, r4_.type()); | |||
} | } | ||
// Tests TestPartResult::file_name(). | // Tests TestPartResult::file_name(). | ||
TEST_F(TestPartResultTe | TEST_F(TestPartResultTe | ||
EXPECT_STREQ("foo/bar.cc", r1_.file_name()); | EXPECT_STREQ("foo/bar.cc", r1_.file_name()); | ||
EXPECT_STREQ(NULL, r3_.file_name()); | EXPECT_STREQ(NULL, r3_.file_name()); | ||
+ EXPECT_STREQ("foo/bar.cc", r4_.file_name()); | |||
} | } | ||
// Tests TestPartResult::line_number(). | // Tests TestPartResult::line_number(). | ||
TEST_F(TestPartResultTe | TEST_F(TestPartResultTe | ||
EXPECT_EQ(10, r1_.line_number()); | EXPECT_EQ(10, r1_.line_number()); | ||
EXPECT_EQ(-1, r2_.line_number()); | EXPECT_EQ(-1, r2_.line_number()); | ||
+ EXPECT_EQ(2, r4_.line_number()); | |||
} | } | ||
// Tests TestPartResult::message(). | // Tests TestPartResult::message(). | ||
TEST_F(TestPartResultTe | TEST_F(TestPartResultTe | ||
EXPECT_STREQ("Success!", r1_.message()); | EXPECT_STREQ("Success!", r1_.message()); | ||
+ EXPECT_STREQ("Skipped!", r4_.message()); | |||
} | } | ||
// Tests TestPartResult::passed(). | // Tests TestPartResult::passed(). | ||
@@ -128,6 +143,7 @@ TEST_F(TestPartR | |||
EXPECT_TRUE(r1_.passed()); | EXPECT_TRUE(r1_.passed()); | ||
EXPECT_FALSE(r2_.passed()); | EXPECT_FALSE(r2_.passed()); | ||
EXPECT_FALSE(r3_.passed()); | EXPECT_FALSE(r3_.passed()); | ||
+ EXPECT_FALSE(r4_.passed()); | |||
} | } | ||
// Tests TestPartResult::failed(). | // Tests TestPartResult::failed(). | ||
@@ -135,6 +151,15 @@ TEST_F(TestPartR | |||
EXPECT_FALSE(r1_.failed()); | EXPECT_FALSE(r1_.failed()); | ||
EXPECT_TRUE(r2_.failed()); | EXPECT_TRUE(r2_.failed()); | ||
EXPECT_TRUE(r3_.failed()); | EXPECT_TRUE(r3_.failed()); | ||
+ EXPECT_FALSE(r4_.failed()); | |||
+} | |||
+ | |||
+// Tests TestPartResult::failed(). | |||
+TEST_F(TestPartResultTe | |||
+ EXPECT_FALSE(r1_.skipped()); | |||
+ EXPECT_FALSE(r2_.skipped()); | |||
+ EXPECT_FALSE(r3_.skipped()); | |||
+ EXPECT_TRUE(r4_.skipped()); | |||
} | } | ||
// Tests TestPartResult::fatally_failed(). | // Tests TestPartResult::fatally_failed(). | ||
@@ -142,6 +167,7 @@ TEST_F(TestPartR | |||
EXPECT_FALSE(r1_.fatally_failed()); | EXPECT_FALSE(r1_.fatally_failed()); | ||
EXPECT_FALSE(r2_.fatally_failed()); | EXPECT_FALSE(r2_.fatally_failed()); | ||
EXPECT_TRUE(r3_.fatally_failed()); | EXPECT_TRUE(r3_.fatally_failed()); | ||
+ EXPECT_FALSE(r4_.fatally_failed()); | |||
} | } | ||
// Tests TestPartResult::nonfatally_faile | // Tests TestPartResult::nonfatally_faile | ||
@@ -149,6 +175,7 @@ TEST_F(TestPartR | |||
EXPECT_FALSE(r1_.nonfatally_faile | EXPECT_FALSE(r1_.nonfatally_faile | ||
EXPECT_TRUE(r2_.nonfatally_faile | EXPECT_TRUE(r2_.nonfatally_faile | ||
EXPECT_FALSE(r3_.nonfatally_faile | EXPECT_FALSE(r3_.nonfatally_faile | ||
+ EXPECT_FALSE(r4_.nonfatally_faile | |||
} | } | ||
// Tests the TestPartResultAr | // Tests the TestPartResultAr |
@@ -37,10 +37,11 @@ | |||
#include "test/googletest-message-test.cc" | #include "test/googletest-message-test.cc" | ||
#include "test/googletest-options-test.cc" | #include "test/googletest-options-test.cc" | ||
#include "test/googletest-port-test.cc" | #include "test/googletest-port-test.cc" | ||
-#include "test/gtest_pred_impl_ | |||
-#include "test/gtest_prod_test.cc" | |||
#include "test/googletest-test-part-test.cc" | #include "test/googletest-test-part-test.cc" | ||
-#include "test/gtest-typed-test_test.cc" | |||
#include "test/gtest-typed-test2_test.cc" | #include "test/gtest-typed-test2_test.cc" | ||
+#include "test/gtest-typed-test_test.cc" | |||
+#include "test/gtest_pred_impl_ | |||
+#include "test/gtest_prod_test.cc" | |||
+#include "test/gtest_skip_test.cc" | |||
#include "test/gtest_unittest.cc" | #include "test/gtest_unittest.cc" | ||
#include "test/production.cc" | #include "test/production.cc" |
@@ -0,0 +1,55 @@ | |||
+// Copyright 2008 Google Inc. | |||
+// All Rights Reserved. | |||
+// | |||
+// Redistribution and use in source and binary forms, with or without | |||
+// modification, are permitted provided that the following conditions are | |||
+// met: | |||
+// | |||
+// * Redistributions of source code must retain the above copyright | |||
+// notice, this list of conditions and the following disclaimer. | |||
+// * Redistributions in binary form must reproduce the above | |||
+// copyright notice, this list of conditions and the following disclaimer | |||
+// in the documentation and/or other materials provided with the | |||
+// distribution. | |||
+// * Neither the name of Google Inc. nor the names of its | |||
+// contributors may be used to endorse or promote products derived from | |||
+// this software without specific prior written permission. | |||
+// | |||
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
+// | |||
+// Author: arseny.aprelev@gmail.com (Arseny Aprelev) | |||
+// | |||
+ | |||
+#include "gtest/gtest.h" | |||
+ | |||
+using ::testing::Test; | |||
+ | |||
+TEST(SkipTest, DoesSkip) { | |||
+ GTEST_SKIP(); | |||
+ EXPECT_EQ(0, 1); | |||
+} | |||
+ | |||
+class Fixture : public Test { | |||
+ protected: | |||
+ void SetUp() override { | |||
+ GTEST_SKIP() << "skipping all tests for this fixture"; | |||
+ } | |||
+}; | |||
+ | |||
+TEST_F(Fixture, SkipsOneTest) { | |||
+ EXPECT_EQ(5, 7); | |||
+} | |||
+ | |||
+TEST_F(Fixture, SkipsAnotherTest | |||
+ EXPECT_EQ(99, 100); | |||
+} |
@@ -36,7 +36,7 @@ std::string getClangReposito | |||
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us | // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us | ||
// pick up a tag in an SVN export, for example. | // pick up a tag in an SVN export, for example. | ||
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/ | + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final/lib/Basic/Version.cpp $"); | ||
if (URL.empty()) { | if (URL.empty()) { | ||
URL = SVNRepository.slice(SVNRepository.find(':'), | URL = SVNRepository.slice(SVNRepository.find(':'), | ||
SVNRepository.find("/lib/Basic")); | SVNRepository.find("/lib/Basic")); |
@@ -122,6 +122,7 @@ struct Configuration { | |||
uint64_t> | uint64_t> | ||
CallGraphProfile | CallGraphProfile | ||
bool AllowMultipleDef | bool AllowMultipleDef | ||
+ bool AllowShlibUndefi | |||
bool AndroidPackDynRe | bool AndroidPackDynRe | ||
bool ARMHasBlx = false; | bool ARMHasBlx = false; | ||
bool ARMHasMovtMovw = false; | bool ARMHasMovtMovw = false; |
@@ -758,6 +758,9 @@ void LinkerDriver::re | |||
Args.hasFlag(OPT_allow_multip | Args.hasFlag(OPT_allow_multip | ||
OPT_no_allow_mul | OPT_no_allow_mul | ||
hasZOption(Args, "muldefs"); | hasZOption(Args, "muldefs"); | ||
+ Config->AllowShlibUndefi | |||
+ Args.hasFlag(OPT_allow_shlib_ | |||
+ Args.hasArg(OPT_shared)); | |||
Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); | Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); | ||
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); | Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); | ||
Config->BsymbolicFunctio | Config->BsymbolicFunctio |
@@ -865,7 +865,7 @@ SharedFile<ELFT> | |||
// Partially parse the shared object file so that we can call | // Partially parse the shared object file so that we can call | ||
// getSoName on this object. | // getSoName on this object. | ||
-template <class ELFT> void | +template <class ELFT> void SharedFile<ELFT>::parseDynamic() { | ||
const Elf_Shdr *DynamicSec = nullptr; | const Elf_Shdr *DynamicSec = nullptr; | ||
const ELFFile<ELFT> Obj = this->getObj(); | const ELFFile<ELFT> Obj = this->getObj(); | ||
ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this); | ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this); | ||
@@ -902,12 +902,16 @@ template <class ELFT> void SharedFile<ELFT> | |||
ArrayRef<Elf_Dyn> Arr = | ArrayRef<Elf_Dyn> Arr = | ||
CHECK(Obj.template getSectionConten | CHECK(Obj.template getSectionConten | ||
for (const Elf_Dyn &Dyn : Arr) { | for (const Elf_Dyn &Dyn : Arr) { | ||
- if (Dyn.d_tag == | + if (Dyn.d_tag == DT_NEEDED) { | ||
+ uint64_t Val = Dyn.getVal(); | |||
+ if (Val >= this->StringTable.size()) | |||
+ fatal(toString(this) + ": invalid DT_NEEDED entry"); | |||
+ DtNeeded.push_back(this->StringTable.data() + Val); | |||
+ } else if (Dyn.d_tag == DT_SONAME) { | |||
uint64_t Val = Dyn.getVal(); | uint64_t Val = Dyn.getVal(); | ||
if (Val >= this->StringTable.size()) | if (Val >= this->StringTable.size()) | ||
fatal(toString(this) + ": invalid DT_SONAME entry"); | fatal(toString(this) + ": invalid DT_SONAME entry"); | ||
SoName = this->StringTable.data() + Val; | SoName = this->StringTable.data() + Val; | ||
- return; | |||
} | } | ||
} | } | ||
} | } | ||
@@ -975,7 +979,7 @@ uint32_t SharedFile<ELFT> | |||
return (Ret > UINT32_MAX) ? 0 : Ret; | return (Ret > UINT32_MAX) ? 0 : Ret; | ||
} | } | ||
-// Fully parse the shared object file. This must be called after | +// Fully parse the shared object file. This must be called after parseDynamic(). | ||
// | // | ||
// This function parses symbol versions. If a DSO has version information, | // This function parses symbol versions. If a DSO has version information, | ||
// the file has a ".gnu.version_d" section which contains symbol version | // the file has a ".gnu.version_d" section which contains symbol version |
@@ -323,6 +323,7 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT | |||
public: | public: | ||
std::vector<const Elf_Verdef *> Verdefs; | std::vector<const Elf_Verdef *> Verdefs; | ||
+ std::vector<StringRef> DtNeeded; | |||
std::string SoName; | std::string SoName; | ||
static bool classof(const InputFile *F) { | static bool classof(const InputFile *F) { | ||
@@ -331,7 +332,7 @@ public: | |||
SharedFile(MemoryBufferRef M, StringRef DefaultSoName); | SharedFile(MemoryBufferRef M, StringRef DefaultSoName); | ||
- void | + void parseDynamic(); | ||
void parseRest(); | void parseRest(); | ||
uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym); | uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym); | ||
std::vector<const Elf_Verdef *> parseVerdefs(); | std::vector<const Elf_Verdef *> parseVerdefs(); | ||
@@ -349,6 +350,9 @@ public: | |||
// data structures in the output file. | // data structures in the output file. | ||
std::map<const Elf_Verdef *, NeededVer> VerdefMap; | std::map<const Elf_Verdef *, NeededVer> VerdefMap; | ||
+ // Used for --no-allow-shlib-undefined. | |||
+ bool AllNeededIsKnown | |||
+ | |||
// Used for --as-needed | // Used for --as-needed | ||
bool IsNeeded; | bool IsNeeded; | ||
}; | }; |
@@ -63,6 +63,10 @@ defm allow_multiple_d | |||
"Allow multiple definitions", | "Allow multiple definitions", | ||
"Do not allow multiple definitions (default)">; | "Do not allow multiple definitions (default)">; | ||
+defm allow_shlib_unde | |||
+ "Allow unresolved references in shared libraries (default when linking a shared library)", | |||
+ "Do not allow unresolved references in shared libraries (default when linking an executable)">; | |||
+ | |||
defm apply_dynamic_re | defm apply_dynamic_re | ||
"Apply link-time values for dynamic relocations", | "Apply link-time values for dynamic relocations", | ||
"Do not apply link-time values for dynamic relocations (default)">; | "Do not apply link-time values for dynamic relocations (default)">; | ||
@@ -492,12 +496,10 @@ def plugin_opt_thinl | |||
def plugin_opt_slash | def plugin_opt_slash | ||
// Options listed below are silently ignored for now for compatibility. | // Options listed below are silently ignored for now for compatibility. | ||
-def: F<"allow-shlib-undefined">; | |||
def: F<"detect-odr-violations">; | def: F<"detect-odr-violations">; | ||
def: Flag<["-"], "g">; | def: Flag<["-"], "g">; | ||
def: F<"long-plt">; | def: F<"long-plt">; | ||
def: F<"no-add-needed">; | def: F<"no-add-needed">; | ||
-def: F<"no-allow-shlib-undefined">; | |||
def: F<"no-copy-dt-needed-entries">; | def: F<"no-copy-dt-needed-entries">; | ||
def: F<"no-ctors-in-init-array">; | def: F<"no-ctors-in-init-array">; | ||
def: F<"no-keep-memory">; | def: F<"no-keep-memory">; |
@@ -93,7 +93,7 @@ template <class ELFT> void SymbolTable::add | |||
// .so file | // .so file | ||
if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { | if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { | ||
// DSOs are uniquified not by filename but by soname. | // DSOs are uniquified not by filename but by soname. | ||
- F- | + F->parseDynamic(); | ||
if (errorCount()) | if (errorCount()) | ||
return; | return; | ||
@@ -80,6 +80,9 @@ public: | |||
void handleDynamicLis | void handleDynamicLis | ||
+ // Set of .so files to not link the same shared object file more than once. | |||
+ llvm::DenseMap<StringRef, InputFile *> SoNames; | |||
+ | |||
private: | private: | ||
std::pair<Symbol *, bool> insertName(StringRef Name); | std::pair<Symbol *, bool> insertName(StringRef Name); | ||
@@ -107,9 +110,6 @@ private: | |||
// is used to uniquify them. | // is used to uniquify them. | ||
llvm::DenseSet<llvm::CachedHashString | llvm::DenseSet<llvm::CachedHashString | ||
- // Set of .so files to not link the same shared object file more than once. | |||
- llvm::DenseMap<StringRef, InputFile *> SoNames; | |||
- | |||
// A map from demangled symbol names to their symbol objects. | // A map from demangled symbol names to their symbol objects. | ||
// This mapping is 1:N because two symbols with different versions | // This mapping is 1:N because two symbols with different versions | ||
// can have the same name. We use this map to handle "extern C++ {}" | // can have the same name. We use this map to handle "extern C++ {}" |
@@ -1668,6 +1668,27 @@ template <class ELFT> void Writer<ELFT>::fi | |||
if (In.Iplt && !In.Iplt->empty()) | if (In.Iplt && !In.Iplt->empty()) | ||
In.Iplt->addSymbols(); | In.Iplt->addSymbols(); | ||
+ if (!Config->AllowShlibUndefi | |||
+ // Error on undefined symbols in a shared object, if all of its DT_NEEDED | |||
+ // entires are seen. These cases would otherwise lead to runtime errors | |||
+ // reported by the dynamic linker. | |||
+ // | |||
+ // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to | |||
+ // catch more cases. That is too much for us. Our approach resembles the one | |||
+ // used in ld.gold, achieves a good balance to be useful but not too smart. | |||
+ for (InputFile *File : SharedFiles) { | |||
+ SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File); | |||
+ F->AllNeededIsKnown | |||
+ return Symtab->SoNames.count(Needed); | |||
+ }); | |||
+ } | |||
+ for (Symbol *Sym : Symtab->getSymbols()) | |||
+ if (Sym->isUndefined() && !Sym->isWeak()) | |||
+ if (auto *F = dyn_cast_or_null | |||
+ if (F->AllNeededIsKnown | |||
+ error(toString(F) + ": undefined reference to " + toString(*Sym)); | |||
+ } | |||
+ | |||
// Now that we have defined all possible global symbols including linker- | // Now that we have defined all possible global symbols including linker- | ||
// synthesized ones. Visit all symbols to give the finishing touches. | // synthesized ones. Visit all symbols to give the finishing touches. | ||
for (Symbol *Sym : Symtab->getSymbols()) { | for (Symbol *Sym : Symtab->getSymbols()) { |
@@ -56,6 +56,9 @@ option. | |||
.It Fl -allow-multiple-definition | .It Fl -allow-multiple-definition | ||
Do not error if a symbol is defined multiple times. | Do not error if a symbol is defined multiple times. | ||
The first definition will be used. | The first definition will be used. | ||
+.It Fl -allow-shlib-undefined | |||
+Allow unresolved references in shared libraries. | |||
+This option is enabled by default when linking a shared library. | |||
.It Fl -apply-dynamic-relocs | .It Fl -apply-dynamic-relocs | ||
Apply link-time values for dynamic relocations. | Apply link-time values for dynamic relocations. | ||
.It Fl -as-needed | .It Fl -as-needed | ||
@@ -252,6 +255,9 @@ Set target emulation. | |||
.It Fl -Map Ns = Ns Ar file , Fl M Ar file | .It Fl -Map Ns = Ns Ar file , Fl M Ar file | ||
Print a link map to | Print a link map to | ||
.Ar file . | .Ar file . | ||
+.It Fl -no-allow-shlib-undefined | |||
+Do not allow unresolved references in shared libraries. | |||
+This option is enabled by default when linking an executable. | |||
.It Fl -no-as-needed | .It Fl -no-as-needed | ||
Always set | Always set | ||
.Dv DT_NEEDED | .Dv DT_NEEDED |
@@ -8,4 +8,4 @@ | |||
#define CLANG_VENDOR "FreeBSD " | #define CLANG_VENDOR "FreeBSD " | ||
-#define SVN_REVISION | +#define SVN_REVISION "356365" |
@@ -7,4 +7,4 @@ | |||
#define LLD_REPOSITORY_S | #define LLD_REPOSITORY_S | ||
// <Upstream revision at import>-<Local identifier in __FreeBSD_versio | // <Upstream revision at import>-<Local identifier in __FreeBSD_versio | ||
-#define LLD_REVISION_STRING | +#define LLD_REVISION_STRING "356365-1300003" |
@@ -1,2 +1,2 @@ | |||
/* $FreeBSD$ */ | /* $FreeBSD$ */ | ||
-#define LLVM_REVISION "svn- | +#define LLVM_REVISION "svn-r356365" |
@@ -18,6 +18,7 @@ GTESTS+= gtest_prod_test | |||
GTESTS+= gtest_sole_heade | GTESTS+= gtest_sole_heade | ||
GTESTS+= googletest-test-part-test | GTESTS+= googletest-test-part-test | ||
GTESTS+= gtest-typed-test_test | GTESTS+= gtest-typed-test_test | ||
+GTESTS+= gtest_skip_test | |||
GTESTS+= gtest_unittest | GTESTS+= gtest_unittest | ||
CXXFLAGS+= -I${GOOGLETEST_SRCRO | CXXFLAGS+= -I${GOOGLETEST_SRCRO |
@@ -1050,14 +1050,8 @@ kldload_param(co | |||
kl = kldload(name); | kl = kldload(name); | ||
else if (strncmp(name, "allow.mount.", 12) == 0) { | else if (strncmp(name, "allow.mount.", 12) == 0) { | ||
/* Load the matching filesystem */ | /* Load the matching filesystem */ | ||
- const char * | + const char *modname = name + 12; | ||
- if (strcmp("fusefs", name + 12) == 0 || | |||
- strcmp("nofusefs", name + 12) == 0) { | |||
- modname = "fuse"; | |||
- } else { | |||
- modname = name + 12; | |||
- } | |||
kl = kldload(modname); | kl = kldload(modname); | ||
if (kl < 0 && errno == ENOENT && | if (kl < 0 && errno == ENOENT && | ||
strncmp(modname, "no", 2) == 0) | strncmp(modname, "no", 2) == 0) |
@@ -501,7 +501,7 @@ init_backgrounde | |||
len = sizeof(ibg); | len = sizeof(ibg); | ||
- if (sysctlbyname("vfs. | + if (sysctlbyname("vfs.fusefs.init_backgrounded", &ibg, &len, NULL, 0)) | ||
return (0); | return (0); | ||
return (ibg); | return (ibg); |
@@ -1071,7 +1071,7 @@ options NFSCL #Network File System client | |||
options AUTOFS #Automounter filesystem | options AUTOFS #Automounter filesystem | ||
options CD9660 #ISO 9660 filesystem | options CD9660 #ISO 9660 filesystem | ||
options FDESCFS #File descriptor filesystem | options FDESCFS #File descriptor filesystem | ||
-options | +options FUSEFS #FUSEFS support module | ||
options MSDOSFS #MS DOS File System (FAT, FAT32) | options MSDOSFS #MS DOS File System (FAT, FAT32) | ||
options NFSLOCKD #Network Lock Manager | options NFSLOCKD #Network Lock Manager | ||
options NFSD #Network Filesystem Server | options NFSD #Network Filesystem Server |
@@ -3494,15 +3494,15 @@ fs/fdescfs/fdesc | |||
fs/fdescfs/fdesc_vnops.c optional fdescfs | fs/fdescfs/fdesc_vnops.c optional fdescfs | ||
fs/fifofs/fifo_vnops.c standard | fs/fifofs/fifo_vnops.c standard | ||
fs/cuse/cuse.c optional cuse | fs/cuse/cuse.c optional cuse | ||
-fs/fuse/fuse_device.c optional | +fs/fuse/fuse_device.c optional fusefs | ||
-fs/fuse/fuse_file.c optional | +fs/fuse/fuse_file.c optional fusefs | ||
-fs/fuse/fuse_internal.c optional | +fs/fuse/fuse_internal.c optional fusefs | ||
-fs/fuse/fuse_io.c optional | +fs/fuse/fuse_io.c optional fusefs | ||
-fs/fuse/fuse_ipc.c optional | +fs/fuse/fuse_ipc.c optional fusefs | ||
-fs/fuse/fuse_main.c optional | +fs/fuse/fuse_main.c optional fusefs | ||
-fs/fuse/fuse_node.c optional | +fs/fuse/fuse_node.c optional fusefs | ||
-fs/fuse/fuse_vfsops.c optional | +fs/fuse/fuse_vfsops.c optional fusefs | ||
-fs/fuse/fuse_vnops.c optional | +fs/fuse/fuse_vnops.c optional fusefs | ||
fs/msdosfs/msdosfs_conv.c optional msdosfs | fs/msdosfs/msdosfs_conv.c optional msdosfs | ||
fs/msdosfs/msdosfs_denode.c optional msdosfs | fs/msdosfs/msdosfs_denode.c optional msdosfs | ||
fs/msdosfs/msdosfs_fat.c optional msdosfs | fs/msdosfs/msdosfs_fat.c optional msdosfs |
@@ -140,6 +140,8 @@ kernel-obj: | |||
.if !defined(NO_MODULES) | .if !defined(NO_MODULES) | ||
modules: modules-all | modules: modules-all | ||
+modules-depend: beforebuild | |||
+modules-all: beforebuild | |||
.if !defined(NO_MODULES_OBJ) | .if !defined(NO_MODULES_OBJ) | ||
modules-all modules-depend: modules-obj | modules-all modules-depend: modules-obj | ||
@@ -328,6 +330,11 @@ ${__obj}: ${OBJS_DEPEND_GU | |||
.depend: .PRECIOUS ${SRCS} | .depend: .PRECIOUS ${SRCS} | ||
+.if ${COMPILER_TYPE} == "clang" || \ | |||
+ (${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION | |||
+_MAP_DEBUG_PREFI | |||
+.endif | |||
+ | |||
_ILINKS= machine | _ILINKS= machine | ||
.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" | .if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" | ||
_ILINKS+= ${MACHINE_CPUARCH} | _ILINKS+= ${MACHINE_CPUARCH} | ||
@@ -337,12 +344,25 @@ _ILINKS+= x86 | |||
.endif | .endif | ||
# Ensure that the link exists without depending on it when it exists. | # Ensure that the link exists without depending on it when it exists. | ||
+# Ensure that debug info references the path in the source tree. | |||
.for _link in ${_ILINKS} | .for _link in ${_ILINKS} | ||
.if !exists(${.OBJDIR}/${_link}) | .if !exists(${.OBJDIR}/${_link}) | ||
${SRCS} ${CLEAN:M*.o}: ${_link} | ${SRCS} ${CLEAN:M*.o}: ${_link} | ||
.endif | .endif | ||
+.if defined(_MAP_DEBUG_PREFI | |||
+.if ${_link} == "machine" | |||
+CFLAGS+= -fdebug-prefix-map=./machine=${SYSDIR}/${MACHINE}/include | |||
+.else | |||
+CFLAGS+= -fdebug-prefix-map=./${_link}=${SYSDIR}/${_link}/include | |||
+.endif | |||
+.endif | |||
.endfor | .endfor | ||
+.if defined(_MAP_DEBUG_PREFI | |||
+# Ensure that DWARF info contains a full path for auto-generated headers. | |||
+CFLAGS+= -fdebug-prefix-map=.=${.OBJDIR} | |||
+.endif | |||
+ | |||
${_ILINKS}: | ${_ILINKS}: | ||
@case ${.TARGET} in \ | @case ${.TARGET} in \ | ||
machine) \ | machine) \ |
@@ -271,6 +271,11 @@ ${FULLPROG}: ${OBJS} | |||
${OBJCOPY} --strip-debug ${.TARGET} | ${OBJCOPY} --strip-debug ${.TARGET} | ||
.endif | .endif | ||
+.if ${COMPILER_TYPE} == "clang" || \ | |||
+ (${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION | |||
+_MAP_DEBUG_PREFI | |||
+.endif | |||
+ | |||
_ILINKS=machine | _ILINKS=machine | ||
.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" | .if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" | ||
_ILINKS+=${MACHINE_CPUARCH} | _ILINKS+=${MACHINE_CPUARCH} | ||
@@ -287,12 +292,25 @@ beforebuild: ${_ILINKS} | |||
# Ensure that the links exist without depending on it when it exists which | # Ensure that the links exist without depending on it when it exists which | ||
# causes all the modules to be rebuilt when the directory pointed to changes. | # causes all the modules to be rebuilt when the directory pointed to changes. | ||
+# Ensure that debug info references the path in the source tree. | |||
.for _link in ${_ILINKS} | .for _link in ${_ILINKS} | ||
.if !exists(${.OBJDIR}/${_link}) | .if !exists(${.OBJDIR}/${_link}) | ||
OBJS_DEPEND_GUES | OBJS_DEPEND_GUES | ||
.endif | .endif | ||
+.if defined(_MAP_DEBUG_PREFI | |||
+.if ${_link} == "machine" | |||
+CFLAGS+= -fdebug-prefix-map=./machine=${SYSDIR}/${MACHINE}/include | |||
+.else | |||
+CFLAGS+= -fdebug-prefix-map=./${_link}=${SYSDIR}/${_link}/include | |||
+.endif | |||
+.endif | |||
.endfor | .endfor | ||
+.if defined(_MAP_DEBUG_PREFI | |||
+# Ensure that DWARF info contains a full path for auto-generated headers. | |||
+CFLAGS+= -fdebug-prefix-map=.=${.OBJDIR} | |||
+.endif | |||
+ | |||
.NOPATH: ${_ILINKS} | .NOPATH: ${_ILINKS} | ||
${_ILINKS}: | ${_ILINKS}: |
@@ -253,7 +253,7 @@ CD9660 opt_dontuse.h | |||
EXT2FS opt_dontuse.h | EXT2FS opt_dontuse.h | ||
FDESCFS opt_dontuse.h | FDESCFS opt_dontuse.h | ||
FFS opt_dontuse.h | FFS opt_dontuse.h | ||
- | +FUSEFS opt_dontuse.h | ||
MSDOSFS opt_dontuse.h | MSDOSFS opt_dontuse.h | ||
NANDFS opt_dontuse.h | NANDFS opt_dontuse.h | ||
NULLFS opt_dontuse.h | NULLFS opt_dontuse.h |
@@ -143,7 +143,7 @@ | |||
/* misc */ | /* misc */ | ||
-SYSCTL_DECL( | +SYSCTL_DECL(_vfs_fusefs); | ||
/* Fuse locking */ | /* Fuse locking */ | ||
@@ -87,7 +87,7 @@ __FBSDID("$FreeB | |||
static int fuse_fh_count = 0; | static int fuse_fh_count = 0; | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, filehandle_count, CTLFLAG_RD, | ||
&fuse_fh_count, 0, "number of open FUSE filehandles"); | &fuse_fh_count, 0, "number of open FUSE filehandles"); | ||
int | int |
@@ -99,21 +99,21 @@ static int fuse_body_audit( | |||
static fuse_handler_t fuse_standard_ha | static fuse_handler_t fuse_standard_ha | ||
-SYSCTL_NODE(_vfs, OID_AUTO, | +SYSCTL_NODE(_vfs, OID_AUTO, fusefs, CTLFLAG_RW, 0, "FUSE tunables"); | ||
-SYSCTL_STRING( | +SYSCTL_STRING(_vfs_fusefs, OID_AUTO, version, CTLFLAG_RD, | ||
FUSE_FREEBSD_VER | FUSE_FREEBSD_VER | ||
static int fuse_ticket_coun | static int fuse_ticket_coun | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, ticket_count, CTLFLAG_RW, | ||
&fuse_ticket_coun | &fuse_ticket_coun | ||
static long fuse_iov_permane | static long fuse_iov_permane | ||
-SYSCTL_LONG( | +SYSCTL_LONG(_vfs_fusefs, OID_AUTO, iov_permanent_bufsize, CTLFLAG_RW, | ||
&fuse_iov_permane | &fuse_iov_permane | ||
"limit for permanently stored buffer size for fuse_iovs"); | "limit for permanently stored buffer size for fuse_iovs"); | ||
static int fuse_iov_credit = 16; | static int fuse_iov_credit = 16; | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, iov_credit, CTLFLAG_RW, | ||
&fuse_iov_credit, | &fuse_iov_credit, | ||
"how many times is an oversized fuse_iov tolerated"); | "how many times is an oversized fuse_iov tolerated"); | ||
@@ -94,9 +94,9 @@ static struct vfsconf fuse_vfsconf = { | |||
.vfc_flags = VFCF_JAIL | VFCF_SYNTHETIC | .vfc_flags = VFCF_JAIL | VFCF_SYNTHETIC | ||
}; | }; | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, kernelabi_major, CTLFLAG_RD, | ||
SYSCTL_NULL_INT_ | SYSCTL_NULL_INT_ | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, kernelabi_minor, CTLFLAG_RD, | ||
SYSCTL_NULL_INT_ | SYSCTL_NULL_INT_ | ||
/****************************** | /****************************** | ||
@@ -156,10 +156,10 @@ fuse_loader(stru | |||
/* Registering the module */ | /* Registering the module */ | ||
static moduledata_t fuse_moddata = { | static moduledata_t fuse_moddata = { | ||
- | + "fusefs", | ||
fuse_loader, | fuse_loader, | ||
&fuse_vfsconf | &fuse_vfsconf | ||
}; | }; | ||
-DECLARE_MODULE( | +DECLARE_MODULE(fusefs, fuse_moddata, SI_SUB_VFS, SI_ORDER_MIDDLE); | ||
-MODULE_VERSION( | +MODULE_VERSION(fusefs, 1); |
@@ -98,47 +98,47 @@ static int sysctl_fuse_cach | |||
static int fuse_node_count = 0; | static int fuse_node_count = 0; | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, node_count, CTLFLAG_RD, | ||
&fuse_node_count, | &fuse_node_count, | ||
int fuse_data_cache_ | int fuse_data_cache_ | ||
-SYSCTL_PROC( | +SYSCTL_PROC(_vfs_fusefs, OID_AUTO, data_cache_mode, CTLTYPE_INT|CTLFLAG_RW, | ||
&fuse_data_cache_ | &fuse_data_cache_ | ||
"Zero: disable caching of FUSE file data; One: write-through caching " | "Zero: disable caching of FUSE file data; One: write-through caching " | ||
"(default); Two: write-back caching (generally unsafe)"); | "(default); Two: write-back caching (generally unsafe)"); | ||
int fuse_data_cache_ | int fuse_data_cache_ | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, data_cache_invalidate, CTLFLAG_RW, | ||
&fuse_data_cache_ | &fuse_data_cache_ | ||
"If non-zero, discard cached clean file data when there are no active file" | "If non-zero, discard cached clean file data when there are no active file" | ||
" users"); | " users"); | ||
int fuse_mmap_enable | int fuse_mmap_enable | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, mmap_enable, CTLFLAG_RW, | ||
&fuse_mmap_enable | &fuse_mmap_enable | ||
"If non-zero, and data_cache_mode is also non-zero, enable mmap(2) of " | "If non-zero, and data_cache_mode is also non-zero, enable mmap(2) of " | ||
"FUSE files"); | "FUSE files"); | ||
int fuse_refresh_siz | int fuse_refresh_siz | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, refresh_size, CTLFLAG_RW, | ||
&fuse_refresh_siz | &fuse_refresh_siz | ||
"If non-zero, and no dirty file extension data is buffered, fetch file " | "If non-zero, and no dirty file extension data is buffered, fetch file " | ||
"size before write operations"); | "size before write operations"); | ||
int fuse_sync_resize | int fuse_sync_resize | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, sync_resize, CTLFLAG_RW, | ||
&fuse_sync_resize | &fuse_sync_resize | ||
"If a cached write extended a file, inform FUSE filesystem of the changed" | "If a cached write extended a file, inform FUSE filesystem of the changed" | ||
"size immediately subsequent to the issued writes"); | "size immediately subsequent to the issued writes"); | ||
int fuse_fix_broken_ | int fuse_fix_broken_ | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, fix_broken_io, CTLFLAG_RW, | ||
&fuse_fix_broken_ | &fuse_fix_broken_ | ||
"If non-zero, print a diagnostic warning if a userspace filesystem returns" | "If non-zero, print a diagnostic warning if a userspace filesystem returns" | ||
" EIO on reads of recently extended portions of files"); | " EIO on reads of recently extended portions of files"); |
@@ -115,16 +115,16 @@ struct vfsops fuse_vfsops = { | |||
.vfs_statfs = fuse_vfsop_statf | .vfs_statfs = fuse_vfsop_statf | ||
}; | }; | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, init_backgrounded, CTLFLAG_RD, | ||
SYSCTL_NULL_INT_ | SYSCTL_NULL_INT_ | ||
static int fuse_enforce_dev | static int fuse_enforce_dev | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, enforce_dev_perms, CTLFLAG_RW, | ||
&fuse_enforce_dev | &fuse_enforce_dev | ||
"enforce fuse device permissions for secondary mounts"); | "enforce fuse device permissions for secondary mounts"); | ||
static unsigned sync_unmount = 1; | static unsigned sync_unmount = 1; | ||
-SYSCTL_UINT( | +SYSCTL_UINT(_vfs_fusefs, OID_AUTO, sync_unmount, CTLFLAG_RW, | ||
&sync_unmount, 0, "specify when to use synchronous unmount"); | &sync_unmount, 0, "specify when to use synchronous unmount"); | ||
MALLOC_DEFINE(M_FUSEVFS, "fuse_filesystem", "buffer for fuse vfs layer"); | MALLOC_DEFINE(M_FUSEVFS, "fuse_filesystem", "buffer for fuse vfs layer"); |
@@ -179,17 +179,17 @@ struct vop_vector fuse_vnops = { | |||
static u_long fuse_lookup_cach | static u_long fuse_lookup_cach | ||
-SYSCTL_ULONG( | +SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_hits, CTLFLAG_RD, | ||
&fuse_lookup_cach | &fuse_lookup_cach | ||
static u_long fuse_lookup_cach | static u_long fuse_lookup_cach | ||
-SYSCTL_ULONG( | +SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_misses, CTLFLAG_RD, | ||
&fuse_lookup_cach | &fuse_lookup_cach | ||
int fuse_lookup_cach | int fuse_lookup_cach | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, lookup_cache_enable, CTLFLAG_RW, | ||
&fuse_lookup_cach | &fuse_lookup_cach | ||
/* | /* | ||
@@ -198,7 +198,7 @@ SYSCTL_INT(_vfs_ | |||
*/ | */ | ||
static int fuse_reclaim_rev | static int fuse_reclaim_rev | ||
-SYSCTL_INT( | +SYSCTL_INT(_vfs_fusefs, OID_AUTO, reclaim_revoked, CTLFLAG_RW, | ||
&fuse_reclaim_rev | &fuse_reclaim_rev | ||
uma_zone_t fuse_pbuf_zone; | uma_zone_t fuse_pbuf_zone; |
@@ -128,7 +128,7 @@ SUBDIR= \ | |||
filemon \ | filemon \ | ||
firewire \ | firewire \ | ||
firmware \ | firmware \ | ||
- | + fusefs \ | ||
${_fxp} \ | ${_fxp} \ | ||
gem \ | gem \ | ||
geom \ | geom \ |
@@ -2,9 +2,12 @@ | |||
.PATH: ${SRCTOP}/sys/fs/fuse | .PATH: ${SRCTOP}/sys/fs/fuse | ||
-KMOD= | +KMOD= fusefs | ||
SRCS= vnode_if.h \ | SRCS= vnode_if.h \ | ||
fuse_node.c fuse_io.c fuse_device.c fuse_ipc.c fuse_file.c \ | fuse_node.c fuse_io.c fuse_device.c fuse_ipc.c fuse_file.c \ | ||
fuse_vfsops.c fuse_vnops.c fuse_internal.c fuse_main.c | fuse_vfsops.c fuse_vnops.c fuse_internal.c fuse_main.c | ||
+# Symlink for backwards compatibility with systems installed at 12.0 or older | |||
+LINKS= ${KMODDIR}/${KMOD}.ko ${KMODDIR}/fuse.ko | |||
+ | |||
.include <bsd.kmod.mk> | .include <bsd.kmod.mk> |
@@ -13970,6 +13970,8 @@ softdep_bp_to_mp | |||
if (LIST_EMPTY(&bp->b_dep)) | if (LIST_EMPTY(&bp->b_dep)) | ||
return (NULL); | return (NULL); | ||
vp = bp->b_vp; | vp = bp->b_vp; | ||
+ KASSERT(vp != NULL, | |||
+ ("%s, buffer with dependencies lacks vnode", __func__)); | |||
/* | /* | ||
* The ump mount point is stable after we get a correct | * The ump mount point is stable after we get a correct | ||
@@ -13979,17 +13981,33 @@ softdep_bp_to_mp | |||
* workitem might be freed while dereferenced. | * workitem might be freed while dereferenced. | ||
*/ | */ | ||
retry: | retry: | ||
- | + switch (vp->v_type) { | ||
+ case VCHR: | |||
VI_LOCK(vp); | VI_LOCK(vp); | ||
mp = vp->v_type == VCHR ? vp->v_rdev->si_mountpt : NULL; | mp = vp->v_type == VCHR ? vp->v_rdev->si_mountpt : NULL; | ||
VI_UNLOCK(vp); | VI_UNLOCK(vp); | ||
if (mp == NULL) | if (mp == NULL) | ||
goto retry; | goto retry; | ||
- } else if (vp->v_type == VREG || vp->v_type == VDIR || | + break; | ||
- vp->v_type == VLNK || vp->v_type == VFIFO) { | + case VREG: | ||
+ case VDIR: | |||
+ case VLNK: | |||
+ case VFIFO: | |||
+ case VSOCK: | |||
mp = vp->v_mount; | mp = vp->v_mount; | ||
- } else { | + break; | ||
- return (NULL); | + case VBLK: | ||
+ vn_printf(vp, "softdep_bp_to_mp | |||
+ /* FALLTHROUGH */ | |||
+ case VNON: | |||
+ case VBAD: | |||
+ case VMARKER: | |||
+ mp = NULL; | |||
+ break; | |||
+ default: | |||
+ vn_printf(vp, "unknown vnode type"); | |||
+ mp = NULL; | |||
+ break; | |||
} | } | ||
return (VFSTOUFS(mp)); | return (VFSTOUFS(mp)); | ||
} | } |