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 |