aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer/minidump_writer.cc
diff options
context:
space:
mode:
authorted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-12-13 22:10:23 +0000
committerted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-12-13 22:10:23 +0000
commitef7262d4775bf6de750bc2a26dbf98368d7ec0c3 (patch)
treea85d6b8c2b66f2da9fdbef3fd0a936dd7f566ac4 /src/client/linux/minidump_writer/minidump_writer.cc
parentReuse code and fix inconsistent array boundaries. (diff)
downloadbreakpad-ef7262d4775bf6de750bc2a26dbf98368d7ec0c3.tar.xz
allow passing info about known memory mappings to MinidumpWriter and ExceptionHandler
r=thestig at http://breakpad.appspot.com/242001/show git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@741 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer/minidump_writer.cc')
-rw-r--r--src/client/linux/minidump_writer/minidump_writer.cc144
1 files changed, 101 insertions, 43 deletions
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc
index 405ec4e8..3eb90953 100644
--- a/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/src/client/linux/minidump_writer/minidump_writer.cc
@@ -368,7 +368,8 @@ class MinidumpWriter {
public:
MinidumpWriter(const char* filename,
pid_t crashing_pid,
- const ExceptionHandler::CrashContext* context)
+ const ExceptionHandler::CrashContext* context,
+ const MappingList& mappings)
: filename_(filename),
siginfo_(&context->siginfo),
ucontext_(&context->context),
@@ -380,7 +381,8 @@ class MinidumpWriter {
#endif
crashing_tid_(context->tid),
dumper_(crashing_pid),
- memory_blocks_(dumper_.allocator()) {
+ memory_blocks_(dumper_.allocator()),
+ mapping_list_(mappings) {
}
bool Init() {
@@ -752,17 +754,34 @@ class MinidumpWriter {
return true;
}
+ // If there is caller-provided information about this mapping
+ // in the mapping_list_ list, return true. Otherwise, return false.
+ bool HaveMappingInfo(const MappingInfo& mapping) {
+ for (MappingList::const_iterator iter = mapping_list_.begin();
+ iter != mapping_list_.end();
+ ++iter) {
+ // Ignore any mappings that are wholly contained within
+ // mappings in the mapping_info_ list.
+ if (mapping.start_addr >= iter->first.start_addr &&
+ (mapping.start_addr + mapping.size) <=
+ (iter->first.start_addr + iter->first.size)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// Write information about the mappings in effect. Because we are using the
// minidump format, the information about the mappings is pretty limited.
// Because of this, we also include the full, unparsed, /proc/$x/maps file in
// another stream in the file.
bool WriteMappings(MDRawDirectory* dirent) {
const unsigned num_mappings = dumper_.mappings().size();
- unsigned num_output_mappings = 0;
+ unsigned num_output_mappings = mapping_list_.size();
for (unsigned i = 0; i < dumper_.mappings().size(); ++i) {
const MappingInfo& mapping = *dumper_.mappings()[i];
- if (ShouldIncludeMapping(mapping))
+ if (ShouldIncludeMapping(mapping) && !HaveMappingInfo(mapping))
num_output_mappings++;
}
@@ -774,56 +793,86 @@ class MinidumpWriter {
dirent->location = list.location();
*list.get() = num_output_mappings;
- for (unsigned i = 0, j = 0; i < num_mappings; ++i) {
+ // First write all the mappings from the dumper
+ unsigned int j = 0;
+ for (unsigned i = 0; i < num_mappings; ++i) {
const MappingInfo& mapping = *dumper_.mappings()[i];
- if (!ShouldIncludeMapping(mapping))
+ if (!ShouldIncludeMapping(mapping) || HaveMappingInfo(mapping))
continue;
MDRawModule mod;
- my_memset(&mod, 0, MD_MODULE_SIZE);
- mod.base_of_image = mapping.start_addr;
- mod.size_of_image = mapping.size;
- const size_t filepath_len = my_strlen(mapping.name);
-
- // Figure out file name from path
- const char* filename_ptr = mapping.name + filepath_len - 1;
- while (filename_ptr >= mapping.name) {
- if (*filename_ptr == '/')
- break;
- filename_ptr--;
- }
- filename_ptr++;
- const size_t filename_len = mapping.name + filepath_len - filename_ptr;
-
- uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX];
- uint8_t* cv_ptr = cv_buf;
- UntypedMDRVA cv(&minidump_writer_);
- if (!cv.Allocate(MDCVInfoPDB70_minsize + filename_len + 1))
+ if (!FillRawModule(mapping, i, mod, NULL))
return false;
+ list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
+ }
+ // Next write all the mappings provided by the caller
+ for (MappingList::const_iterator iter = mapping_list_.begin();
+ iter != mapping_list_.end();
+ ++iter) {
+ MDRawModule mod;
+ if (!FillRawModule(iter->first, -1, mod, iter->second))
+ return false;
+ list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
+ }
- const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
- memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
- cv_ptr += sizeof(cv_signature);
- uint8_t* signature = cv_ptr;
- cv_ptr += sizeof(MDGUID);
- dumper_.ElfFileIdentifierForMapping(i, signature);
- my_memset(cv_ptr, 0, sizeof(uint32_t)); // Set age to 0 on Linux.
- cv_ptr += sizeof(uint32_t);
+ return true;
+ }
- // Write pdb_file_name
- memcpy(cv_ptr, filename_ptr, filename_len + 1);
- cv.Copy(cv_buf, MDCVInfoPDB70_minsize + filename_len + 1);
+ // Fill the MDRawModule |mod| with information about the provided
+ // |mapping|. If |identifier| is non-NULL, use it instead of calculating
+ // a file ID from the mapping. |mapping_id| can be -1 if this mapping
+ // is not from the LinuxDumper.
+ bool FillRawModule(const MappingInfo& mapping,
+ unsigned int mapping_id,
+ MDRawModule& mod,
+ const u_int8_t* identifier) {
+ my_memset(&mod, 0, MD_MODULE_SIZE);
+
+ mod.base_of_image = mapping.start_addr;
+ mod.size_of_image = mapping.size;
+ const size_t filepath_len = my_strlen(mapping.name);
+
+ // Figure out file name from path
+ const char* filename_ptr = mapping.name + filepath_len - 1;
+ while (filename_ptr >= mapping.name) {
+ if (*filename_ptr == '/')
+ break;
+ filename_ptr--;
+ }
+ filename_ptr++;
- mod.cv_record = cv.location();
+ const size_t filename_len = mapping.name + filepath_len - filename_ptr;
- MDLocationDescriptor ld;
- if (!minidump_writer_.WriteString(mapping.name, filepath_len, &ld))
- return false;
- mod.module_name_rva = ld.rva;
+ uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX];
+ uint8_t* cv_ptr = cv_buf;
+ UntypedMDRVA cv(&minidump_writer_);
+ if (!cv.Allocate(MDCVInfoPDB70_minsize + filename_len + 1))
+ return false;
- list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
+ const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
+ memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
+ cv_ptr += sizeof(cv_signature);
+ uint8_t* signature = cv_ptr;
+ cv_ptr += sizeof(MDGUID);
+ if (identifier) {
+ // GUID was provided by caller.
+ memcpy(signature, identifier, sizeof(MDGUID));
+ } else {
+ dumper_.ElfFileIdentifierForMapping(mapping, mapping_id, signature);
}
+ my_memset(cv_ptr, 0, sizeof(uint32_t)); // Set age to 0 on Linux.
+ cv_ptr += sizeof(uint32_t);
+ // Write pdb_file_name
+ memcpy(cv_ptr, filename_ptr, filename_len + 1);
+ cv.Copy(cv_buf, MDCVInfoPDB70_minsize + filename_len + 1);
+
+ mod.cv_record = cv.location();
+
+ MDLocationDescriptor ld;
+ if (!minidump_writer_.WriteString(mapping.name, filepath_len, &ld))
+ return false;
+ mod.module_name_rva = ld.rva;
return true;
}
@@ -1233,15 +1282,24 @@ class MinidumpWriter {
// written while writing the thread list stream, but saved here
// so a memory list stream can be written afterwards.
wasteful_vector<MDMemoryDescriptor> memory_blocks_;
+ // Additional information about some mappings provided by the caller.
+ const MappingList& mapping_list_;
};
bool WriteMinidump(const char* filename, pid_t crashing_process,
const void* blob, size_t blob_size) {
+ MappingList m;
+ return WriteMinidump(filename, crashing_process, blob, blob_size, m);
+}
+
+bool WriteMinidump(const char* filename, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings) {
if (blob_size != sizeof(ExceptionHandler::CrashContext))
return false;
const ExceptionHandler::CrashContext* context =
reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
- MinidumpWriter writer(filename, crashing_process, context);
+ MinidumpWriter writer(filename, crashing_process, context, mappings);
if (!writer.Init())
return false;
return writer.Dump();