OLD | NEW |
1 // Copyright 2013 Google Inc. All rights reserved. | 1 // Copyright 2013 Google Inc. All rights reserved. |
2 // | 2 // |
3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
5 // met: | 5 // met: |
6 // | 6 // |
7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
10 // copyright notice, this list of conditions and the following disclaimer | 10 // copyright notice, this list of conditions and the following disclaimer |
(...skipping 13 matching lines...) Expand all Loading... |
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | 28 |
29 // Utilities for loading debug streams and tables from a PDB file. | 29 // Utilities for loading debug streams and tables from a PDB file. |
30 | 30 |
31 #ifndef COMMON_WINDOWS_DIA_UTIL_H_ | 31 #ifndef COMMON_WINDOWS_DIA_UTIL_H_ |
32 #define COMMON_WINDOWS_DIA_UTIL_H_ | 32 #define COMMON_WINDOWS_DIA_UTIL_H_ |
33 | 33 |
| 34 #include <cassert> |
| 35 |
34 #include <Windows.h> | 36 #include <Windows.h> |
35 #include <dia2.h> | 37 #include <dia2.h> |
36 | 38 |
37 namespace google_breakpad { | 39 namespace google_breakpad { |
38 | 40 |
39 // Find the debug stream of the given |name| in the given |session|. Returns | 41 // Find the debug stream of the given |name| in the given |session|. Returns |
40 // true on success, false on error of if the stream does not exist. On success | 42 // true on success, false on error of if the stream does not exist. On success |
41 // the stream will be returned via |debug_stream|. | 43 // the stream will be returned via |debug_stream|. |
42 bool FindDebugStream(const wchar_t* name, | 44 bool FindDebugStream(const wchar_t* name, |
43 IDiaSession* session, | 45 IDiaSession* session, |
44 IDiaEnumDebugStreamData** debug_stream); | 46 IDiaEnumDebugStreamData** debug_stream); |
45 | 47 |
| 48 // A template which finds the debug stream with the given |name| in the given |
| 49 // |session|, and populates |table|, a vector of a fixed size type |
| 50 // |T::value_type|, with the stream's contents, cast directly into |T|. |rva| |
| 51 // contains the base RVA of the the debug stream if available, otherwise 0. |
| 52 template <typename T> |
| 53 bool FindAndLoadDebugStream(const wchar_t* name, |
| 54 IDiaSession* session, |
| 55 T* table, |
| 56 DWORD *rva) { |
| 57 assert(name != NULL); |
| 58 assert(session != NULL); |
| 59 assert(table != NULL); |
| 60 *rva = 0; |
| 61 |
| 62 CComPtr<IDiaEnumDebugStreamData> stream; |
| 63 if (!FindDebugStream(name, session, &stream)) |
| 64 return false; |
| 65 assert(stream.p != NULL); |
| 66 |
| 67 LONG count = 0; |
| 68 if (FAILED(stream->get_Count(&count))) { |
| 69 fprintf(stderr, "IDiaEnumDebugStreamData::get_Count failed for stream " |
| 70 "\"%ws\"\n", name); |
| 71 return false; |
| 72 } |
| 73 |
| 74 // Get the length of the stream in bytes. |
| 75 DWORD bytes_read = 0; |
| 76 ULONG count_read = 0; |
| 77 if (FAILED(stream->Next(count, 0, &bytes_read, NULL, &count_read))) { |
| 78 fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading " |
| 79 "length of stream \"%ws\"\n", name); |
| 80 return false; |
| 81 } |
| 82 |
| 83 // Ensure it's consistent with the data type. |
| 84 DWORD bytes_expected = count * sizeof(T::value_type); |
| 85 if (count * sizeof(T::value_type) != bytes_read) { |
| 86 fprintf(stderr, "DIA debug stream \"%ws\" has an unexpected length", name); |
| 87 return false; |
| 88 } |
| 89 |
| 90 // Get the RVA, if available |
| 91 CComPtr<IDiaImageData> pImageData; |
| 92 if (SUCCEEDED(stream->QueryInterface(__uuidof(IDiaImageData), |
| 93 (void **)&pImageData))) { |
| 94 pImageData->get_relativeVirtualAddress(rva); |
| 95 } |
| 96 |
| 97 // Read the table. |
| 98 table->resize(count); |
| 99 bytes_read = 0; |
| 100 count_read = 0; |
| 101 if (FAILED(stream->Next(count, bytes_expected, &bytes_read, |
| 102 reinterpret_cast<BYTE*>(&table->at(0)), |
| 103 &count_read))) { |
| 104 fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading " |
| 105 "data from stream \"%ws\"\n", name); |
| 106 return false; |
| 107 } |
| 108 |
| 109 return true; |
| 110 } |
| 111 |
46 // Finds the first table implementing the COM interface with ID |iid| in the | 112 // Finds the first table implementing the COM interface with ID |iid| in the |
47 // given |session|. Returns true on success, false on error or if no such | 113 // given |session|. Returns true on success, false on error or if no such |
48 // table is found. On success the table will be returned via |table|. | 114 // table is found. On success the table will be returned via |table|. |
49 bool FindTable(REFIID iid, IDiaSession* session, void** table); | 115 bool FindTable(REFIID iid, IDiaSession* session, void** table); |
50 | 116 |
51 // A templated version of FindTable. Finds the first table implementing type | 117 // A templated version of FindTable. Finds the first table implementing type |
52 // |InterfaceType| in the given |session|. Returns true on success, false on | 118 // |InterfaceType| in the given |session|. Returns true on success, false on |
53 // error or if no such table is found. On success the table will be returned via | 119 // error or if no such table is found. On success the table will be returned via |
54 // |table|. | 120 // |table|. |
55 template<typename InterfaceType> | 121 template<typename InterfaceType> |
56 bool FindTable(IDiaSession* session, InterfaceType** table) { | 122 bool FindTable(IDiaSession* session, InterfaceType** table) { |
57 return FindTable(__uuidof(InterfaceType), | 123 return FindTable(__uuidof(InterfaceType), |
58 session, | 124 session, |
59 reinterpret_cast<void**>(table)); | 125 reinterpret_cast<void**>(table)); |
60 } | 126 } |
61 | 127 |
62 } // namespace google_breakpad | 128 } // namespace google_breakpad |
63 | 129 |
64 #endif // COMMON_WINDOWS_DIA_UTIL_H_ | 130 #endif // COMMON_WINDOWS_DIA_UTIL_H_ |
OLD | NEW |