Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: src/processor/minidump.cc

Issue 1251593007: Add support for Linux memory mapping stream and remove ELF header usage (Closed) Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 Google Inc. 1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 #define PRIx32 "lx" 48 #define PRIx32 "lx"
49 #define snprintf _snprintf 49 #define snprintf _snprintf
50 #else // _WIN32 50 #else // _WIN32
51 #include <unistd.h> 51 #include <unistd.h>
52 #endif // _WIN32 52 #endif // _WIN32
53 53
54 #include <fstream> 54 #include <fstream>
55 #include <iostream> 55 #include <iostream>
56 #include <limits> 56 #include <limits>
57 #include <map> 57 #include <map>
58 #include <sstream>
58 #include <vector> 59 #include <vector>
59 60
60 #include "processor/range_map-inl.h" 61 #include "processor/range_map-inl.h"
61 62
62 #include "common/scoped_ptr.h" 63 #include "common/scoped_ptr.h"
63 #include "google_breakpad/processor/dump_context.h" 64 #include "google_breakpad/processor/dump_context.h"
64 #include "processor/basic_code_module.h" 65 #include "processor/basic_code_module.h"
65 #include "processor/basic_code_modules.h" 66 #include "processor/basic_code_modules.h"
66 #include "processor/logging.h" 67 #include "processor/logging.h"
67 68
68 namespace google_breakpad { 69 namespace google_breakpad {
69 70
70 71
71 using std::istream; 72 using std::istream;
72 using std::ifstream; 73 using std::ifstream;
73 using std::numeric_limits; 74 using std::numeric_limits;
75 using std::stringstream;
74 using std::vector; 76 using std::vector;
75 77
76 // Returns true iff |context_size| matches exactly one of the sizes of the 78 // Returns true iff |context_size| matches exactly one of the sizes of the
77 // various MDRawContext* types. 79 // various MDRawContext* types.
78 // TODO(blundell): This function can be removed once 80 // TODO(blundell): This function can be removed once
79 // http://code.google.com/p/google-breakpad/issues/detail?id=550 is fixed. 81 // http://code.google.com/p/google-breakpad/issues/detail?id=550 is fixed.
80 static bool IsContextSizeUnique(uint32_t context_size) { 82 static bool IsContextSizeUnique(uint32_t context_size) {
81 int num_matching_contexts = 0; 83 int num_matching_contexts = 0;
82 if (context_size == sizeof(MDRawContextX86)) 84 if (context_size == sizeof(MDRawContextX86))
83 num_matching_contexts++; 85 num_matching_contexts++;
(...skipping 3881 matching lines...) Expand 10 before | Expand all | Expand 10 after
3965 3967
3966 for (unsigned int info_index = 0; 3968 for (unsigned int info_index = 0;
3967 info_index < info_count_; 3969 info_index < info_count_;
3968 ++info_index) { 3970 ++info_index) {
3969 printf("info[%d]\n", info_index); 3971 printf("info[%d]\n", info_index);
3970 (*infos_)[info_index].Print(); 3972 (*infos_)[info_index].Print();
3971 printf("\n"); 3973 printf("\n");
3972 } 3974 }
3973 } 3975 }
3974 3976
3977 //
3978 // MinidumpLinuxMaps
3979 //
3980
3981 MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump *minidump)
3982 : MinidumpObject(minidump),
3983 pathname_(),
3984 raw_linux_maps_(NULL) {
3985 }
3986
3987 MinidumpLinuxMaps::~MinidumpLinuxMaps() {
3988 delete raw_linux_maps_;
3989 }
3990
3991 bool MinidumpLinuxMaps::Read(vector<char> *data) {
ivanpe 2015/07/23 01:17:12 There is already an implementation of this in Chro
liuandrew 2015/07/23 16:14:50 How do I reuse the Chromium code? Do I just copy t
liuandrew 2015/07/24 23:25:36 Done.
3992 valid_ = false;
3993
3994 // Convert data vector into stringstream.
3995 string str = "";
3996 for (unsigned int i = 0; i < data->size(); i++) {
3997 str.push_back((*data)[i]);
3998 }
3999 stringstream stream(str);
4000 delete data;
4001 data = NULL;
4002
4003 // Tokenize the string stream.
4004 string address, perms, offset, dev, inode;
4005 stream >> address >> perms >> offset >> dev >> inode >> pathname_;
4006 // Check if the tokens are filled. The pathname is optional.
4007 if (address.size() <= 0
4008 || perms.size() <= 0
4009 || offset.size() <= 0
4010 || dev.size() <= 0
4011 || inode.size() <= 0) {
4012 BPLOG(ERROR) << "Malformed input string: not enough tokens";
4013 return false;
4014 }
4015
4016 // Load base address and region size.
4017 size_t address_delimiter_index = address.find("-");
4018 if (address_delimiter_index == string::npos) {
4019 BPLOG(ERROR) << "Address delimiter not found";
4020 return false;
4021 }
4022 uint64_t end_address = 0;
4023 stringstream(address.substr(0, address_delimiter_index))
4024 >> std::hex
4025 >> base_address_;
4026 stringstream(address.substr(address_delimiter_index + 1, address.size()))
4027 >> std::hex
4028 >> end_address;
4029 if (base_address_ > end_address) {
4030 BPLOG(ERROR) << "Base address greater than end address: "
4031 << base_address_
4032 << " > "
4033 << end_address;
4034 return false;
4035 }
4036 region_size_ = end_address - base_address_;
4037
4038 // Load permissions.
4039 if (perms.size() != 4) {
4040 BPLOG(ERROR) << "Permission string incorrectly loaded";
4041 return false;
4042 }
4043 if (perms[0] == 'r') {
4044 is_readable_ = true;
4045 } else if (perms[0] == '-') {
4046 is_readable_ = false;
4047 } else {
4048 BPLOG(ERROR) << "Invalid permission character: " << perms[0];
4049 return false;
4050 }
4051 if (perms[1] == 'w') {
4052 is_writeable_ = true;
4053 } else if (perms[1] == '-') {
4054 is_writeable_ = false;
4055 } else {
4056 BPLOG(ERROR) << "Invalid permission character: " << perms[1];
4057 return false;
4058 }
4059 if (perms[2] == 'x') {
4060 is_executable_ = true;
4061 } else if (perms[2] == '-') {
4062 is_executable_ = false;
4063 } else {
4064 BPLOG(ERROR) << "Invalid permission character: " << perms[2];
4065 return false;
4066 }
4067 if (perms[3] == 's') {
4068 is_shared_ = true;
4069 } else if (perms[3] == 'p') {
4070 is_shared_ = false;
4071 } else {
4072 BPLOG(ERROR) << "Invalid permission character: " << perms[3];
4073 return false;
4074 }
4075
4076 // Load offset.
4077 stringstream(offset) >> std::hex >> offset_;
4078
4079 // Load major and minor devices.
4080 size_t device_delimiter_index = dev.find(":");
4081 if (device_delimiter_index == string::npos) {
4082 BPLOG(ERROR) << "Device delimiter not found";
4083 return false;
4084 }
4085 uint64_t major_container, minor_container;
4086 stringstream(dev.substr(0, device_delimiter_index))
4087 >> std::hex
4088 >> major_container;
4089 stringstream(dev.substr(device_delimiter_index + 1, dev.size()))
4090 >> std::hex
4091 >> minor_container;
4092 major_device_ = static_cast<uint8_t>(major_container);
4093 minor_device_ = static_cast<uint8_t>(minor_container);
4094
4095 // Load inode.
4096 stringstream(inode) >> inode_;
4097
4098 valid_ = true;
4099 return true;
4100 }
4101
4102 void MinidumpLinuxMaps::Print() {
4103 if (!valid_) {
4104 BPLOG(ERROR) << "MinidumpLinuxMaps cannot print invalid data";
4105 return;
4106 }
4107 // Print the contents of raw_linux_maps_.
4108 for (unsigned int i = 0; i < raw_linux_maps_->size(); i++) {
4109 printf("%c", (*raw_linux_maps_)[i]);
4110 }
4111 }
4112
4113 //
4114 // MinidumpLinuxMapsList
4115 //
4116
4117 MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump *minidump)
4118 : MinidumpStream(minidump),
4119 maps_(NULL),
4120 maps_count_(0),
4121 raw_linux_maps_list_() {
4122 }
4123
4124 MinidumpLinuxMapsList::~MinidumpLinuxMapsList() {
4125 for (unsigned int i = 0; i < maps_->size(); i++) {
4126 delete (*maps_)[i];
4127 }
4128 delete maps_;
4129 }
4130
4131 const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsForAddress(
4132 uint64_t address) const {
4133 if (!valid_) {
4134 BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress";
4135 return NULL;
4136 }
4137
4138 // Search every memory mapping.
4139 for (unsigned int index = 0; index < maps_count_; index++) {
4140 // Check if address is within bounds of the current memory region.
4141 if ((*maps_)[index]->GetBase() <= address &&
4142 (*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) {
4143 return (*maps_)[index];
4144 }
4145 }
4146
4147 // No mapping encloses the memory address.
4148 BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at "
4149 << HexString(address);
4150 return NULL;
4151 }
4152
4153 const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsAtIndex(
4154 unsigned int index) const {
4155 if (!valid_) {
4156 BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex";
4157 return NULL;
4158 }
4159
4160 // Index out of bounds.
4161 if (index >= maps_count_) {
4162 BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: "
4163 << index
4164 << "/"
4165 << maps_count_;
4166 return NULL;
4167 }
4168 return (*maps_)[index];
4169 }
4170
4171 bool MinidumpLinuxMapsList::Read(uint32_t expected_size) {
4172 // Invalidate cached data.
4173 delete maps_;
4174 maps_ = NULL;
4175 maps_count_ = 0;
4176 raw_linux_maps_list_.clear();
4177
4178 valid_ = false;
4179
4180 // Load and check expected stream length.
4181 uint32_t length = 0;
4182 if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) {
4183 BPLOG(ERROR) << "MinidumpLinuxMapsList stream type not found";
4184 return false;
4185 }
4186 if (expected_size != length) {
4187 BPLOG(ERROR) << "MinidumpLinuxMapsList size mismatch: "
4188 << expected_size
4189 << " != "
4190 << length;
4191 return false;
4192 }
4193
4194 // Read data from stream into raw_linux_maps_list_.
4195 raw_linux_maps_list_.resize(length);
4196 if (!minidump_->ReadBytes(&raw_linux_maps_list_[0], length)) {
4197 BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read bytes";
4198 return false;
4199 }
4200 scoped_ptr<vector<char> > map_data(new vector<char>());
4201 scoped_ptr<MinidumpLinuxMaps> map_entry(new MinidumpLinuxMaps(minidump_));
4202 scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings());
4203
4204 // Load all of the raw list into a list of MinidumpLinuxMaps.
4205 for (unsigned int i = 0; i < raw_linux_maps_list_.size(); i++) {
4206 // Push character into data buffer.
4207 map_data->push_back(raw_linux_maps_list_[i]);
4208
4209 // A newline marks the end of a mapping entry.
4210 if (raw_linux_maps_list_[i] == '\n') {
4211 // Read entry data into MinidumpLinuxMaps object.
4212 if (!map_entry->Read(map_data.release())) {
4213 BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read entry";
4214 return false;
4215 }
4216 // Add completed map entry into vector.
4217 maps->push_back(map_entry.release());
4218
4219 // Reset scoped pointers.
4220 map_data.reset(new vector<char>());
4221 map_entry.reset(new MinidumpLinuxMaps(minidump_));
4222 }
4223 }
4224
4225 // Set instance variables.
4226 maps_ = maps.release();
4227 maps_count_ = maps_->size();
4228 valid_ = true;
4229 return true;
4230 }
4231
4232 void MinidumpLinuxMapsList::Print() {
4233 if (!valid_) {
4234 BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data";
4235 return;
4236 }
4237
4238 // Print contents of raw_linux_maps_list_.
4239 for (unsigned int i = 0; i < raw_linux_maps_list_.size(); i++) {
4240 printf("%c", raw_linux_maps_list_[i]);
4241 }
4242 }
3975 4243
3976 // 4244 //
3977 // Minidump 4245 // Minidump
3978 // 4246 //
3979 4247
3980 4248
3981 uint32_t Minidump::max_streams_ = 128; 4249 uint32_t Minidump::max_streams_ = 128;
3982 unsigned int Minidump::max_string_length_ = 1024; 4250 unsigned int Minidump::max_string_length_ = 1024;
3983 4251
3984 4252
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
4285 MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() { 4553 MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
4286 MinidumpBreakpadInfo* breakpad_info; 4554 MinidumpBreakpadInfo* breakpad_info;
4287 return GetStream(&breakpad_info); 4555 return GetStream(&breakpad_info);
4288 } 4556 }
4289 4557
4290 MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() { 4558 MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
4291 MinidumpMemoryInfoList* memory_info_list; 4559 MinidumpMemoryInfoList* memory_info_list;
4292 return GetStream(&memory_info_list); 4560 return GetStream(&memory_info_list);
4293 } 4561 }
4294 4562
4563 MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() {
4564 MinidumpLinuxMapsList *linux_maps_list;
4565 return GetStream(&linux_maps_list);
4566 }
4567
4295 static const char* get_stream_name(uint32_t stream_type) { 4568 static const char* get_stream_name(uint32_t stream_type) {
4296 switch (stream_type) { 4569 switch (stream_type) {
4297 case MD_UNUSED_STREAM: 4570 case MD_UNUSED_STREAM:
4298 return "MD_UNUSED_STREAM"; 4571 return "MD_UNUSED_STREAM";
4299 case MD_RESERVED_STREAM_0: 4572 case MD_RESERVED_STREAM_0:
4300 return "MD_RESERVED_STREAM_0"; 4573 return "MD_RESERVED_STREAM_0";
4301 case MD_RESERVED_STREAM_1: 4574 case MD_RESERVED_STREAM_1:
4302 return "MD_RESERVED_STREAM_1"; 4575 return "MD_RESERVED_STREAM_1";
4303 case MD_THREAD_LIST_STREAM: 4576 case MD_THREAD_LIST_STREAM:
4304 return "MD_THREAD_LIST_STREAM"; 4577 return "MD_THREAD_LIST_STREAM";
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
4622 return NULL; 4895 return NULL;
4623 } 4896 }
4624 4897
4625 *stream = new_stream.release(); 4898 *stream = new_stream.release();
4626 info->stream = *stream; 4899 info->stream = *stream;
4627 return *stream; 4900 return *stream;
4628 } 4901 }
4629 4902
4630 4903
4631 } // namespace google_breakpad 4904 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698