Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |