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 1835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1846 case MD_OS_WIN32_WINDOWS: { | 1846 case MD_OS_WIN32_WINDOWS: { |
| 1847 // Use the same format that the MS symbol server uses in filesystem | 1847 // Use the same format that the MS symbol server uses in filesystem |
| 1848 // hierarchies. | 1848 // hierarchies. |
| 1849 char identifier_string[17]; | 1849 char identifier_string[17]; |
| 1850 snprintf(identifier_string, sizeof(identifier_string), "%08X%x", | 1850 snprintf(identifier_string, sizeof(identifier_string), "%08X%x", |
| 1851 module_.time_date_stamp, module_.size_of_image); | 1851 module_.time_date_stamp, module_.size_of_image); |
| 1852 identifier = identifier_string; | 1852 identifier = identifier_string; |
| 1853 break; | 1853 break; |
| 1854 } | 1854 } |
| 1855 | 1855 |
| 1856 case MD_OS_ANDROID: | |
| 1857 case MD_OS_LINUX: { | |
| 1858 // If ELF CodeView data is present, return the debug id. | |
| 1859 if (cv_record_ && cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { | |
| 1860 const MDCVInfoELF* cv_record_elf = | |
| 1861 reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); | |
| 1862 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); | |
| 1863 | |
| 1864 for (unsigned int build_id_index = 0; | |
| 1865 build_id_index < (cv_record_->size() - MDCVInfoELF_minsize); | |
| 1866 ++build_id_index) { | |
| 1867 char byte[3]; | |
|
Mark Mentovai
2016/02/09 19:27:05
build_id[build_id_index] is the byte, this is a st
| |
| 1868 snprintf(byte, sizeof(byte), "%02x", | |
| 1869 cv_record_elf->build_id[build_id_index]); | |
| 1870 identifier += byte; | |
| 1871 } | |
| 1872 break; | |
| 1873 } | |
| 1874 // Otherwise fall through to the case below. | |
| 1875 } | |
| 1876 | |
| 1856 case MD_OS_MAC_OS_X: | 1877 case MD_OS_MAC_OS_X: |
| 1857 case MD_OS_IOS: | 1878 case MD_OS_IOS: |
| 1858 case MD_OS_SOLARIS: | 1879 case MD_OS_SOLARIS: |
| 1859 case MD_OS_ANDROID: | |
| 1860 case MD_OS_LINUX: | |
| 1861 case MD_OS_NACL: | 1880 case MD_OS_NACL: |
| 1862 case MD_OS_PS3: { | 1881 case MD_OS_PS3: { |
| 1863 // TODO(mmentovai): support uuid extension if present, otherwise fall | 1882 // TODO(mmentovai): support uuid extension if present, otherwise fall |
| 1864 // back to version (from LC_ID_DYLIB?), otherwise fall back to something | 1883 // back to version (from LC_ID_DYLIB?), otherwise fall back to something |
| 1865 // else. | 1884 // else. |
| 1866 identifier = "id"; | 1885 identifier = "id"; |
| 1867 break; | 1886 break; |
| 1868 } | 1887 } |
| 1869 | 1888 |
| 1870 default: { | 1889 default: { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1901 // GetCVRecord guarantees pdb_file_name is null-terminated. | 1920 // GetCVRecord guarantees pdb_file_name is null-terminated. |
| 1902 file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name); | 1921 file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name); |
| 1903 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { | 1922 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { |
| 1904 // It's actually an MDCVInfoPDB20 structure. | 1923 // It's actually an MDCVInfoPDB20 structure. |
| 1905 const MDCVInfoPDB20* cv_record_20 = | 1924 const MDCVInfoPDB20* cv_record_20 = |
| 1906 reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); | 1925 reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); |
| 1907 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); | 1926 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); |
| 1908 | 1927 |
| 1909 // GetCVRecord guarantees pdb_file_name is null-terminated. | 1928 // GetCVRecord guarantees pdb_file_name is null-terminated. |
| 1910 file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name); | 1929 file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name); |
| 1930 } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { | |
| 1931 // It's actually an MDCVInfoELF structure. | |
| 1932 const MDCVInfoELF* cv_record_elf = | |
| 1933 reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); | |
| 1934 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); | |
| 1935 | |
| 1936 // For MDCVInfoELF, the debug file is the code file. | |
| 1937 file = *name_; | |
| 1911 } | 1938 } |
| 1912 | 1939 |
| 1913 // If there's a CodeView record but it doesn't match a known signature, | 1940 // If there's a CodeView record but it doesn't match a known signature, |
| 1914 // try the miscellaneous record. | 1941 // try the miscellaneous record. |
| 1915 } | 1942 } |
| 1916 | 1943 |
| 1917 if (file.empty()) { | 1944 if (file.empty()) { |
| 1918 // No usable CodeView record. Try the miscellaneous debug record. | 1945 // No usable CodeView record. Try the miscellaneous debug record. |
| 1919 if (misc_record_) { | 1946 if (misc_record_) { |
| 1920 const MDImageDebugMisc* misc_record = | 1947 const MDImageDebugMisc* misc_record = |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1952 } | 1979 } |
| 1953 } | 1980 } |
| 1954 | 1981 |
| 1955 // Relatively common case | 1982 // Relatively common case |
| 1956 BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine " | 1983 BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine " |
| 1957 "debug_file for " << *name_; | 1984 "debug_file for " << *name_; |
| 1958 | 1985 |
| 1959 return file; | 1986 return file; |
| 1960 } | 1987 } |
| 1961 | 1988 |
| 1989 static string guid_and_age_to_debug_id(const MDGUID& guid, | |
| 1990 uint32_t age) { | |
| 1991 char identifier_string[41]; | |
| 1992 snprintf(identifier_string, sizeof(identifier_string), | |
| 1993 "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x", | |
| 1994 guid.data1, | |
| 1995 guid.data2, | |
| 1996 guid.data3, | |
| 1997 guid.data4[0], | |
| 1998 guid.data4[1], | |
| 1999 guid.data4[2], | |
| 2000 guid.data4[3], | |
| 2001 guid.data4[4], | |
| 2002 guid.data4[5], | |
| 2003 guid.data4[6], | |
| 2004 guid.data4[7], | |
| 2005 age); | |
| 2006 return identifier_string; | |
| 2007 } | |
| 1962 | 2008 |
| 1963 string MinidumpModule::debug_identifier() const { | 2009 string MinidumpModule::debug_identifier() const { |
| 1964 if (!valid_) { | 2010 if (!valid_) { |
| 1965 BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier"; | 2011 BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier"; |
| 1966 return ""; | 2012 return ""; |
| 1967 } | 2013 } |
| 1968 | 2014 |
| 1969 if (!has_debug_info_) | 2015 if (!has_debug_info_) |
| 1970 return ""; | 2016 return ""; |
| 1971 | 2017 |
| 1972 string identifier; | 2018 string identifier; |
| 1973 | 2019 |
| 1974 // Use the CodeView record if present. | 2020 // Use the CodeView record if present. |
| 1975 if (cv_record_) { | 2021 if (cv_record_) { |
| 1976 if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { | 2022 if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { |
| 1977 // It's actually an MDCVInfoPDB70 structure. | 2023 // It's actually an MDCVInfoPDB70 structure. |
| 1978 const MDCVInfoPDB70* cv_record_70 = | 2024 const MDCVInfoPDB70* cv_record_70 = |
| 1979 reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); | 2025 reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); |
| 1980 assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); | 2026 assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); |
| 1981 | 2027 |
| 1982 // Use the same format that the MS symbol server uses in filesystem | 2028 // Use the same format that the MS symbol server uses in filesystem |
| 1983 // hierarchies. | 2029 // hierarchies. |
| 1984 char identifier_string[41]; | 2030 identifier = guid_and_age_to_debug_id(cv_record_70->signature, |
| 1985 snprintf(identifier_string, sizeof(identifier_string), | 2031 cv_record_70->age); |
| 1986 "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x", | |
| 1987 cv_record_70->signature.data1, | |
| 1988 cv_record_70->signature.data2, | |
| 1989 cv_record_70->signature.data3, | |
| 1990 cv_record_70->signature.data4[0], | |
| 1991 cv_record_70->signature.data4[1], | |
| 1992 cv_record_70->signature.data4[2], | |
| 1993 cv_record_70->signature.data4[3], | |
| 1994 cv_record_70->signature.data4[4], | |
| 1995 cv_record_70->signature.data4[5], | |
| 1996 cv_record_70->signature.data4[6], | |
| 1997 cv_record_70->signature.data4[7], | |
| 1998 cv_record_70->age); | |
| 1999 identifier = identifier_string; | |
| 2000 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { | 2032 } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { |
| 2001 // It's actually an MDCVInfoPDB20 structure. | 2033 // It's actually an MDCVInfoPDB20 structure. |
| 2002 const MDCVInfoPDB20* cv_record_20 = | 2034 const MDCVInfoPDB20* cv_record_20 = |
| 2003 reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); | 2035 reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); |
| 2004 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); | 2036 assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); |
| 2005 | 2037 |
| 2006 // Use the same format that the MS symbol server uses in filesystem | 2038 // Use the same format that the MS symbol server uses in filesystem |
| 2007 // hierarchies. | 2039 // hierarchies. |
| 2008 char identifier_string[17]; | 2040 char identifier_string[17]; |
| 2009 snprintf(identifier_string, sizeof(identifier_string), | 2041 snprintf(identifier_string, sizeof(identifier_string), |
| 2010 "%08X%x", cv_record_20->signature, cv_record_20->age); | 2042 "%08X%x", cv_record_20->signature, cv_record_20->age); |
| 2011 identifier = identifier_string; | 2043 identifier = identifier_string; |
| 2044 } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { | |
| 2045 // It's actually an MDCVInfoELF structure. | |
| 2046 const MDCVInfoELF* cv_record_elf = | |
| 2047 reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); | |
| 2048 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); | |
| 2049 | |
| 2050 // For backwards-compatibility, stuff as many bytes as will fit into | |
| 2051 // a MDGUID and use the MS symbol server format as MDCVInfoPDB70 does | |
| 2052 // with age = 0. Historically Breakpad would do this during dump | |
| 2053 // writing to fit the build id data into a MDCVInfoPDB70 struct. | |
| 2054 // The full build id is available by calling code_identifier. | |
| 2055 MDGUID guid = {0}; | |
| 2056 memcpy(&guid, &cv_record_elf->build_id, | |
| 2057 cv_record_->size() - MDCVInfoELF_minsize); | |
| 2058 identifier = guid_and_age_to_debug_id(guid, 0); | |
| 2012 } | 2059 } |
| 2013 } | 2060 } |
| 2014 | 2061 |
| 2015 // TODO(mmentovai): if there's no usable CodeView record, there might be a | 2062 // TODO(mmentovai): if there's no usable CodeView record, there might be a |
| 2016 // miscellaneous debug record. It only carries a filename, though, and no | 2063 // miscellaneous debug record. It only carries a filename, though, and no |
| 2017 // identifier. I'm not sure what the right thing to do for the identifier | 2064 // identifier. I'm not sure what the right thing to do for the identifier |
| 2018 // is in that case, but I don't expect to find many modules without a | 2065 // is in that case, but I don't expect to find many modules without a |
| 2019 // CodeView record (or some other Breakpad extension structure in place of | 2066 // CodeView record (or some other Breakpad extension structure in place of |
| 2020 // a CodeView record). Treat it as an error (empty identifier) for now. | 2067 // a CodeView record). Treat it as an error (empty identifier) for now. |
| 2021 | 2068 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2160 // quantities. (It's a path, is it UTF-8?) | 2207 // quantities. (It's a path, is it UTF-8?) |
| 2161 } | 2208 } |
| 2162 | 2209 |
| 2163 // The last field of either structure is null-terminated 8-bit character | 2210 // The last field of either structure is null-terminated 8-bit character |
| 2164 // data. Ensure that it's null-terminated. | 2211 // data. Ensure that it's null-terminated. |
| 2165 if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { | 2212 if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { |
| 2166 BPLOG(ERROR) << "MindumpModule CodeView2 record string is not " | 2213 BPLOG(ERROR) << "MindumpModule CodeView2 record string is not " |
| 2167 "0-terminated"; | 2214 "0-terminated"; |
| 2168 return NULL; | 2215 return NULL; |
| 2169 } | 2216 } |
| 2217 } else if (signature == MD_CVINFOELF_SIGNATURE) { | |
| 2218 // Now that the structure type is known, recheck the size. | |
| 2219 if (MDCVInfoELF_minsize > module_.cv_record.data_size) { | |
| 2220 BPLOG(ERROR) << "MinidumpModule CodeViewELF record size mismatch, " << | |
| 2221 MDCVInfoELF_minsize << " > " << | |
| 2222 module_.cv_record.data_size; | |
| 2223 return NULL; | |
| 2224 } | |
| 2225 // There's nothing to swap in CVInfoELF, it's just raw bytes. | |
| 2170 } | 2226 } |
| 2171 | 2227 |
| 2172 // If the signature doesn't match something above, it's not something | 2228 // If the signature doesn't match something above, it's not something |
| 2173 // that Breakpad can presently handle directly. Because some modules in | 2229 // that Breakpad can presently handle directly. Because some modules in |
| 2174 // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE, | 2230 // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE, |
| 2175 // don't bail out here - allow the data to be returned to the user, | 2231 // don't bail out here - allow the data to be returned to the user, |
| 2176 // although byte-swapping can't be done. | 2232 // although byte-swapping can't be done. |
| 2177 | 2233 |
| 2178 // Store the vector type because that's how storage was allocated, but | 2234 // Store the vector type because that's how storage was allocated, but |
| 2179 // return it casted to uint8_t*. | 2235 // return it casted to uint8_t*. |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2360 cv_record_20->cv_header.signature); | 2416 cv_record_20->cv_header.signature); |
| 2361 printf(" (cv_record).cv_header.offset = 0x%x\n", | 2417 printf(" (cv_record).cv_header.offset = 0x%x\n", |
| 2362 cv_record_20->cv_header.offset); | 2418 cv_record_20->cv_header.offset); |
| 2363 printf(" (cv_record).signature = 0x%x %s\n", | 2419 printf(" (cv_record).signature = 0x%x %s\n", |
| 2364 cv_record_20->signature, | 2420 cv_record_20->signature, |
| 2365 TimeTToUTCString(cv_record_20->signature).c_str()); | 2421 TimeTToUTCString(cv_record_20->signature).c_str()); |
| 2366 printf(" (cv_record).age = %d\n", | 2422 printf(" (cv_record).age = %d\n", |
| 2367 cv_record_20->age); | 2423 cv_record_20->age); |
| 2368 printf(" (cv_record).pdb_file_name = \"%s\"\n", | 2424 printf(" (cv_record).pdb_file_name = \"%s\"\n", |
| 2369 cv_record_20->pdb_file_name); | 2425 cv_record_20->pdb_file_name); |
| 2426 } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { | |
| 2427 const MDCVInfoELF* cv_record_elf = | |
| 2428 reinterpret_cast<const MDCVInfoELF*>(cv_record); | |
| 2429 assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); | |
| 2430 | |
| 2431 printf(" (cv_record).cv_signature = 0x%x\n", | |
| 2432 cv_record_elf->cv_signature); | |
| 2433 printf(" (cv_record).build_id = "); | |
| 2434 for (unsigned int build_id_index = 0; | |
| 2435 build_id_index < (cv_record_size - MDCVInfoELF_minsize); | |
| 2436 ++build_id_index) { | |
| 2437 printf("%02x", cv_record_elf->build_id[build_id_index]); | |
| 2438 } | |
| 2439 printf("\n"); | |
| 2370 } else { | 2440 } else { |
| 2371 printf(" (cv_record) = "); | 2441 printf(" (cv_record) = "); |
| 2372 for (unsigned int cv_byte_index = 0; | 2442 for (unsigned int cv_byte_index = 0; |
| 2373 cv_byte_index < cv_record_size; | 2443 cv_byte_index < cv_record_size; |
| 2374 ++cv_byte_index) { | 2444 ++cv_byte_index) { |
| 2375 printf("%02x", cv_record[cv_byte_index]); | 2445 printf("%02x", cv_record[cv_byte_index]); |
| 2376 } | 2446 } |
| 2377 printf("\n"); | 2447 printf("\n"); |
| 2378 } | 2448 } |
| 2379 } else { | 2449 } else { |
| (...skipping 2406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4786 return NULL; | 4856 return NULL; |
| 4787 } | 4857 } |
| 4788 | 4858 |
| 4789 *stream = new_stream.release(); | 4859 *stream = new_stream.release(); |
| 4790 info->stream = *stream; | 4860 info->stream = *stream; |
| 4791 return *stream; | 4861 return *stream; |
| 4792 } | 4862 } |
| 4793 | 4863 |
| 4794 | 4864 |
| 4795 } // namespace google_breakpad | 4865 } // namespace google_breakpad |
| OLD | NEW |