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 |