mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 861141 - Connect Breakpad on Android to faulty.lib's mmap interface. r=glandium,ted
This commit is contained in:
parent
3be2bb313f
commit
1f8653bbbc
@ -0,0 +1,50 @@
|
||||
# HG changeset patch
|
||||
# User Julian Seward <jseward@acm.org>
|
||||
# Date 1365953823 -7200
|
||||
# Node ID 21d2964d1337c0fce7375025610298a818ddbd0f
|
||||
# Parent ef802a6418f25841880359e6dab3e8240bfd0821
|
||||
Bug 861141 - Connect Breakpad on Android to faulty.lib's mmap interface. r=ted.
|
||||
Adds a prototype for ReadSymbolDataInternal so it can be called from
|
||||
outside breakpad.
|
||||
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
|
||||
@@ -36,16 +36,17 @@
|
||||
#define COMMON_LINUX_DUMP_SYMBOLS_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/symbol_data.h"
|
||||
#include "common/using_std_string.h"
|
||||
+#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class Module;
|
||||
|
||||
// Find all the debugging information in OBJ_FILE, an ELF executable
|
||||
// or shared library, and write it to SYM_STREAM in the Breakpad symbol
|
||||
// file format.
|
||||
@@ -60,11 +61,19 @@ bool WriteSymbolFile(const string &obj_f
|
||||
// As above, but simply return the debugging information in MODULE
|
||||
// instead of writing it to a stream. The caller owns the resulting
|
||||
// Module object and must delete it when finished.
|
||||
bool ReadSymbolData(const string& obj_file,
|
||||
const std::vector<string>& debug_dirs,
|
||||
SymbolData symbol_data,
|
||||
Module** module);
|
||||
|
||||
+// Same as ReadSymbolData, except don't try to open the file; instead
|
||||
+// just use the in-memory data (mapped image of it) located at OBJ_FILE.
|
||||
+bool ReadSymbolDataInternal(const uint8_t* obj_file,
|
||||
+ const string& obj_filename,
|
||||
+ const std::vector<string>& debug_dirs,
|
||||
+ SymbolData symbol_data,
|
||||
+ Module** module);
|
||||
+
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "common/symbol_data.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
@ -65,6 +66,14 @@ bool ReadSymbolData(const string& obj_file,
|
||||
SymbolData symbol_data,
|
||||
Module** module);
|
||||
|
||||
// Same as ReadSymbolData, except don't try to open the file; instead
|
||||
// just use the in-memory data (mapped image of it) located at OBJ_FILE.
|
||||
bool ReadSymbolDataInternal(const uint8_t* obj_file,
|
||||
const string& obj_filename,
|
||||
const std::vector<string>& debug_dirs,
|
||||
SymbolData symbol_data,
|
||||
Module** module);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
|
||||
|
@ -26,6 +26,16 @@
|
||||
# error "Unknown platform"
|
||||
#endif
|
||||
|
||||
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
|
||||
# include "mozilla/Types.h"
|
||||
# include "ElfLoader.h"
|
||||
# include <dlfcn.h>
|
||||
# include <sys/mman.h>
|
||||
# include "nsString.h"
|
||||
# include "nsDirectoryServiceUtils.h"
|
||||
# include "nsDirectoryServiceDefs.h"
|
||||
#endif
|
||||
|
||||
#include "local_debug_info_symbolizer.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
@ -40,6 +50,98 @@ LocalDebugInfoSymbolizer::~LocalDebugInfoSymbolizer() {
|
||||
# endif
|
||||
}
|
||||
|
||||
#if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
|
||||
|
||||
// Find out where the installation's lib directory is, since we'll
|
||||
// have to look in there to get hold of libmozglue.so. Returned
|
||||
// C string is heap allocated and the caller must deallocate it.
|
||||
static char* get_installation_lib_dir ( void )
|
||||
{
|
||||
nsCOMPtr<nsIProperties>
|
||||
directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
if (!directoryService) return NULL;
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(greDir));
|
||||
if (NS_FAILED(rv)) return NULL;
|
||||
nsCString path;
|
||||
rv = greDir->GetNativePath(path);
|
||||
if (NS_FAILED(rv)) return NULL;
|
||||
return strdup(path.get());
|
||||
}
|
||||
|
||||
// Read symbol data from a file on Android. OBJ_FILENAME has
|
||||
// three possible cases:
|
||||
//
|
||||
// (1) /foo/bar/xyzzy/blah.apk!/libwurble.so
|
||||
// We hand it as-is to faulty.lib and let it fish the relevant
|
||||
// bits out of the APK.
|
||||
//
|
||||
// (2) libmozglue.so
|
||||
// This is part of the Fennec installation, but is not in the
|
||||
// APK. Instead we have to figure out the installation path
|
||||
// and look for it there.
|
||||
//
|
||||
// (3) libanythingelse.so
|
||||
// faulty.lib assumes this is a system library, and prepends
|
||||
// "/system/lib/" to the path. So as in (1), we can give it
|
||||
// as-is to faulty.lib.
|
||||
//
|
||||
// Hence only (2) requires special-casing here.
|
||||
//
|
||||
static bool ReadSymbolData_ANDROID(const string& obj_filename,
|
||||
const std::vector<string>& debug_dirs,
|
||||
SymbolData symbol_data,
|
||||
Module** module)
|
||||
{
|
||||
string obj_file_to_use = obj_filename;
|
||||
|
||||
// Do (2) in the comment above.
|
||||
if (obj_file_to_use == "libmozglue.so") {
|
||||
char* libdir = get_installation_lib_dir();
|
||||
if (libdir) {
|
||||
obj_file_to_use = string(libdir) + "/lib/" + obj_file_to_use;
|
||||
free(libdir);
|
||||
}
|
||||
}
|
||||
|
||||
// Regardless of whether the file is inside an APK or not, we ask
|
||||
// faulty.lib to map it, then call ReadSymbolDataInternal, then
|
||||
// unmap and dlclose it.
|
||||
void* hdl = dlopen(obj_file_to_use.c_str(), RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (!hdl) {
|
||||
BPLOG(INFO) << "ReadSymbolData_APK: Failed to get handle for ELF file \'"
|
||||
<< obj_file_to_use << "\'";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t sz = __dl_get_mappable_length(hdl);
|
||||
if (sz == 0) {
|
||||
dlclose(hdl);
|
||||
BPLOG(INFO) << "ReadSymbolData_APK: Unable to get size for ELF file \'"
|
||||
<< obj_file_to_use << "\'";
|
||||
return false;
|
||||
}
|
||||
|
||||
void* image = __dl_mmap(hdl, NULL, sz, 0);
|
||||
if (image == MAP_FAILED) {
|
||||
dlclose(hdl);
|
||||
BPLOG(INFO) << "ReadSymbolData_APK: Failed to mmap ELF file \'"
|
||||
<< obj_file_to_use << "\'";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = ReadSymbolDataInternal((const uint8_t*)image,
|
||||
obj_file_to_use, debug_dirs,
|
||||
symbol_data, module);
|
||||
__dl_munmap(hdl, image, sz);
|
||||
dlclose(hdl);
|
||||
|
||||
return ok;
|
||||
}
|
||||
#endif /* defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK) */
|
||||
|
||||
|
||||
StackFrameSymbolizer::SymbolizerResult
|
||||
LocalDebugInfoSymbolizer::FillSourceLineInfo(const CodeModules* modules,
|
||||
const SystemInfo* system_info,
|
||||
@ -61,10 +163,17 @@ LocalDebugInfoSymbolizer::FillSourceLineInfo(const CodeModules* modules,
|
||||
no_symbol_modules_.end()) {
|
||||
return kNoError;
|
||||
}
|
||||
if (!ReadSymbolData(module->code_file(),
|
||||
debug_dirs_,
|
||||
ONLY_CFI,
|
||||
&debug_info_module)) {
|
||||
|
||||
bool ok = false;
|
||||
# if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
|
||||
ok = ReadSymbolData_ANDROID(module->code_file(), debug_dirs_,
|
||||
ONLY_CFI, &debug_info_module);
|
||||
# else
|
||||
ok = ReadSymbolData(module->code_file(), debug_dirs_,
|
||||
ONLY_CFI, &debug_info_module);
|
||||
# endif
|
||||
|
||||
if (!ok) {
|
||||
if (debug_info_module)
|
||||
delete debug_info_module;
|
||||
no_symbol_modules_.insert(module->code_file());
|
||||
|
Loading…
Reference in New Issue
Block a user