Bug 1471532 - Support Windows in ASan Nightly Reporter builds. r=froydnj

MozReview-Commit-ID: AK2dBOgoazY

--HG--
extra : rebase_source : 6ed99ce79180f2a6f2d54a0898cb02acbd6e9fb6
This commit is contained in:
Christian Holler 2018-06-27 11:19:00 +02:00
parent c57ab475c6
commit bdf8e4d393
6 changed files with 81 additions and 23 deletions

View File

@ -29,6 +29,10 @@ logger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
logger.addAppender(new Log.DumpAppender(new Log.BasicFormatter()));
logger.level = Preferences.get(PREF_LOG_LEVEL, Log.Level.Info);
// Determine the directory where ASan dumps will be located
let profileDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
let asanDumpDir = OS.Path.join(profileDir.path, "asan");
this.TabCrashObserver = {
init() {
if (this.initialized)
@ -44,7 +48,7 @@ this.TabCrashObserver = {
if (!aSubject.get("abnormal")) {
return;
}
processDirectory("/tmp");
processDirectory(asanDumpDir);
}
},
};
@ -60,15 +64,7 @@ function startup(aData, aReason) {
// after they happen instead of relying on the user to restart the browser.
TabCrashObserver.init();
// We could use OS.Constants.Path.tmpDir here, but unfortunately there is
// no way in C++ to get the same value *prior* to xpcom initialization.
// Since ASan needs its options, including the "log_path" option already
// at early startup, there is no way to pass this on to ASan.
//
// Instead, we hardcode the /tmp directory here, which should be fine in
// most cases, as long as we are on Linux and Mac (the main targets for
// this addon at the time of writing).
processDirectory("/tmp");
processDirectory(asanDumpDir);
}
function shutdown(aData, aReason) {

View File

@ -2,7 +2,7 @@
mkdir tmp/
git clone --no-checkout --depth 1 https://github.com/choller/firefox-asan-reporter tmp/
(cd tmp && git reset --hard d508c6e3f5df752a9a7a2d6f1e4e7261ec2290e7)
(cd tmp && git reset --hard c42a0b9c131c90cec2a2e93efb77e02e1673316f)
# Copy only whitelisted files
cp tmp/bootstrap.js tmp/install.rdf.in tmp/moz.build tmp/README.md tmp/LICENSE .

View File

@ -32,14 +32,6 @@
// allocations the same way we would handle them with a regular allocator and
// also uncovers potential bugs that might occur in these situations.
//
// log_path=/tmp/ff_asan_log - When running with the ASan reporter extension
// enabled (MOZ_ASAN_REPORTER), then we need to dump our logs to files
// instead of stderr so the reporter extension can find it. Unfortunately,
// this function is called so early at startup that we can't use the profile
// directory or even ask XPCOM for a temporary directory. Since the extension
// is only meant to run on Linux and Mac OSX for now, hardcoding /tmp is an
// option that should work for most standard environments.
//
// max_malloc_fill_size - Tell ASan to initialize memory to a certain value
// when it is allocated. This option specifies the maximum allocation size
// for which ASan should still initialize the memory. The value we specify
@ -61,9 +53,7 @@ const char* __asan_default_options() {
return "allow_user_segv_handler=1:alloc_dealloc_mismatch=0:detect_leaks=0"
":max_free_fill_size=268435456:max_malloc_fill_size=268435456"
":malloc_fill_byte=228:free_fill_byte=229"
#ifdef MOZ_ASAN_REPORTER
":log_path=/tmp/ff_asan_log"
#endif
":handle_sigill=1"
":allocator_may_return_null=1";
}

View File

@ -341,7 +341,10 @@ SaveFileToEnv(const char *name, nsIFile *file)
}
// Load the path of a file saved with SaveFileToEnv
static already_AddRefed<nsIFile>
#ifndef MOZ_ASAN_REPORTER
static
#endif
already_AddRefed<nsIFile>
GetFileFromEnv(const char *name)
{
nsresult rv;
@ -4245,6 +4248,18 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
CrashReporter::SetProfileDirectory(mProfD);
#ifdef MOZ_ASAN_REPORTER
// In ASan reporter builds, we need to set ASan's log_path as early as
// possible, so it dumps its errors into files there instead of using
// the default stderr location. Since this is crucial for ASan reporter
// to work at all (and we don't want people to use a non-functional
// ASan reporter build), all failures while setting log_path are fatal.
setASanReporterPath(mProfD);
// Export to env for child processes
SaveFileToEnv("ASAN_REPORTER_PATH", mProfD);
#endif
nsAutoCString version;
BuildVersion(version);
@ -5294,3 +5309,32 @@ extern "C" void
GeckoHandleOOM(size_t size) {
mozalloc_handle_oom(size);
}
#ifdef MOZ_ASAN_REPORTER
void setASanReporterPath(nsIFile* aDir) {
nsCOMPtr<nsIFile> dir;
aDir->Clone(getter_AddRefs(dir));
dir->Append(NS_LITERAL_STRING("asan"));
nsresult rv = dir->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) {
MOZ_CRASH("[ASan Reporter] Unable to create crash directory.");
}
dir->Append(NS_LITERAL_STRING("ff_asan_log"));
#ifdef XP_WIN
nsAutoString nspathW;
rv = dir->GetPath(nspathW);
NS_ConvertUTF16toUTF8 nspath(nspathW);
#else
nsAutoCString nspath;
rv = dir->GetNativePath(nspath);
#endif
if (NS_FAILED(rv)) {
MOZ_CRASH("[ASan Reporter] Unable to get native path for crash directory.");
}
__sanitizer_set_report_path(nspath.get());
}
#endif

View File

@ -129,4 +129,14 @@ const char* PlatformBuildID();
*/
void SetupErrorHandling(const char* progname);
#ifdef MOZ_ASAN_REPORTER
extern "C" {
void MOZ_EXPORT __sanitizer_set_report_path(const char *path);
}
void setASanReporterPath(nsIFile* aDir);
already_AddRefed<nsIFile> GetFileFromEnv(const char *name);
#endif
#endif // nsAppRunner_h__

View File

@ -360,6 +360,24 @@ XRE_InitChildProcess(int aArgc,
NS_ENSURE_ARG_POINTER(aArgv[0]);
MOZ_ASSERT(aChildData);
#ifdef MOZ_ASAN_REPORTER
// In ASan reporter builds, we need to set ASan's log_path as early as
// possible, so it dumps its errors into files there instead of using
// the default stderr location. Since this is crucial for ASan reporter
// to work at all (and we don't want people to use a non-functional
// ASan reporter build), all failures while setting log_path are fatal.
//
// We receive this log_path via the ASAN_REPORTER_PATH environment variable
// because there is no other way to generically get the necessary profile
// directory in all child types without adding support for that in each
// child process type class (at the risk of missing this in a child).
nsCOMPtr<nsIFile> asanReporterPath = GetFileFromEnv("ASAN_REPORTER_PATH");
if (!asanReporterPath) {
MOZ_CRASH("Child did not receive ASAN_REPORTER_PATH!");
}
setASanReporterPath(asanReporterPath);
#endif
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
// This has to happen before glib thread pools are started.
mozilla::SandboxEarlyInit();