Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: src/common/linux/file_id.cc

Issue 1688743002: Switch the Linux minidump writer to use MDCVInfoELF for CV data. (Closed) Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2006, Google Inc. 1 // Copyright (c) 2006, 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 30 matching lines...) Expand all
41 #include <algorithm> 41 #include <algorithm>
42 42
43 #include "common/linux/elf_gnu_compat.h" 43 #include "common/linux/elf_gnu_compat.h"
44 #include "common/linux/elfutils.h" 44 #include "common/linux/elfutils.h"
45 #include "common/linux/linux_libc_support.h" 45 #include "common/linux/linux_libc_support.h"
46 #include "common/linux/memory_mapped_file.h" 46 #include "common/linux/memory_mapped_file.h"
47 #include "third_party/lss/linux_syscall_support.h" 47 #include "third_party/lss/linux_syscall_support.h"
48 48
49 namespace google_breakpad { 49 namespace google_breakpad {
50 50
51 // Used in a few places for backwards-compatibility.
52 const size_t kMDGUIDSize = sizeof(MDGUID);
53
51 FileID::FileID(const char* path) : path_(path) {} 54 FileID::FileID(const char* path) : path_(path) {}
52 55
53 // ELF note name and desc are 32-bits word padded. 56 // ELF note name and desc are 32-bits word padded.
54 #define NOTE_PADDING(a) ((a + 3) & ~3) 57 #define NOTE_PADDING(a) ((a + 3) & ~3)
55 58
56 // These functions are also used inside the crashed process, so be safe 59 // These functions are also used inside the crashed process, so be safe
57 // and use the syscall/libc wrappers instead of direct syscalls or libc. 60 // and use the syscall/libc wrappers instead of direct syscalls or libc.
58 61
59 template<typename ElfClass> 62 template<typename ElfClass>
60 static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, 63 static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
61 uint8_t identifier[kMDGUIDSize]) { 64 uint8_t identifier[kMaxBuildID],
65 size_t* identifier_length) {
62 typedef typename ElfClass::Nhdr Nhdr; 66 typedef typename ElfClass::Nhdr Nhdr;
63 67
68 assert(identifier_length);
69
64 const void* section_end = reinterpret_cast<const char*>(section) + length; 70 const void* section_end = reinterpret_cast<const char*>(section) + length;
65 const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section); 71 const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section);
66 while (reinterpret_cast<const void *>(note_header) < section_end) { 72 while (reinterpret_cast<const void *>(note_header) < section_end) {
67 if (note_header->n_type == NT_GNU_BUILD_ID) 73 if (note_header->n_type == NT_GNU_BUILD_ID)
68 break; 74 break;
69 note_header = reinterpret_cast<const Nhdr*>( 75 note_header = reinterpret_cast<const Nhdr*>(
70 reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) + 76 reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
71 NOTE_PADDING(note_header->n_namesz) + 77 NOTE_PADDING(note_header->n_namesz) +
72 NOTE_PADDING(note_header->n_descsz)); 78 NOTE_PADDING(note_header->n_descsz));
73 } 79 }
74 if (reinterpret_cast<const void *>(note_header) >= section_end || 80 if (reinterpret_cast<const void *>(note_header) >= section_end ||
75 note_header->n_descsz == 0) { 81 note_header->n_descsz == 0) {
76 return false; 82 return false;
77 } 83 }
78 84
79 const char* build_id = reinterpret_cast<const char*>(note_header) + 85 const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) +
80 sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz); 86 sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
81 // Copy as many bits of the build ID as will fit 87 // Copy as many bits of the build ID as will fit
82 // into the GUID space. 88 // into |identifier|. This should always fit unless someone has
83 my_memset(identifier, 0, kMDGUIDSize); 89 // passed --build-id=0x... to the linker with a longer-than-standard
84 memcpy(identifier, build_id, 90 // hex string.
85 std::min(kMDGUIDSize, (size_t)note_header->n_descsz)); 91 my_memset(identifier, 0, kMaxBuildID);
92 *identifier_length = std::min(kMaxBuildID, (size_t)note_header->n_descsz);
93 memcpy(identifier, build_id, *identifier_length);
86 94
87 return true; 95 return true;
88 } 96 }
89 97
90 // Attempt to locate a .note.gnu.build-id section in an ELF binary 98 // Attempt to locate a .note.gnu.build-id section in an ELF binary
91 // and copy as many bytes of it as will fit into |identifier|. 99 // and copy as many bytes of it as will fit into |identifier|.
100 // Set |*identifier_length| to the number of bytes copied.
92 static bool FindElfBuildIDNote(const void *elf_mapped_base, 101 static bool FindElfBuildIDNote(const void *elf_mapped_base,
93 uint8_t identifier[kMDGUIDSize]) { 102 uint8_t identifier[kMaxBuildID],
103 size_t* identifier_length) {
104 assert(identifier_length);
94 void* note_section; 105 void* note_section;
95 size_t note_size; 106 size_t note_size;
96 int elfclass; 107 int elfclass;
97 if ((!FindElfSegment(elf_mapped_base, PT_NOTE, 108 if ((!FindElfSegment(elf_mapped_base, PT_NOTE,
98 (const void**)&note_section, &note_size, &elfclass) || 109 (const void**)&note_section, &note_size, &elfclass) ||
99 note_size == 0) && 110 note_size == 0) &&
100 (!FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE, 111 (!FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
101 (const void**)&note_section, &note_size, &elfclass) || 112 (const void**)&note_section, &note_size, &elfclass) ||
102 note_size == 0)) { 113 note_size == 0)) {
103 return false; 114 return false;
104 } 115 }
105 116
106 if (elfclass == ELFCLASS32) { 117 if (elfclass == ELFCLASS32) {
107 return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size, 118 return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size,
108 identifier); 119 identifier,
120 identifier_length);
109 } else if (elfclass == ELFCLASS64) { 121 } else if (elfclass == ELFCLASS64) {
110 return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size, 122 return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size,
111 identifier); 123 identifier,
124 identifier_length);
112 } 125 }
113 126
114 return false; 127 return false;
115 } 128 }
116 129
117 // Attempt to locate the .text section of an ELF binary and generate 130 // Attempt to locate the .text section of an ELF binary and generate
118 // a simple hash by XORing the first page worth of bytes into |identifier|. 131 // a simple hash by XORing the first page worth of bytes into |identifier|.
119 static bool HashElfTextSection(const void *elf_mapped_base, 132 static bool HashElfTextSection(const void *elf_mapped_base,
120 uint8_t identifier[kMDGUIDSize]) { 133 uint8_t identifier[kMaxBuildID],
134 size_t* identifier_length) {
135 assert(identifier_length);
121 void* text_section; 136 void* text_section;
122 size_t text_size; 137 size_t text_size;
123 if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS, 138 if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
124 (const void**)&text_section, &text_size, NULL) || 139 (const void**)&text_section, &text_size, NULL) ||
125 text_size == 0) { 140 text_size == 0) {
126 return false; 141 return false;
127 } 142 }
128 143
144 // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
145 // function backwards-compatible.
129 my_memset(identifier, 0, kMDGUIDSize); 146 my_memset(identifier, 0, kMDGUIDSize);
130 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section); 147 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
131 const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096)); 148 const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096));
132 while (ptr < ptr_end) { 149 while (ptr < ptr_end) {
133 for (unsigned i = 0; i < kMDGUIDSize; i++) 150 for (unsigned i = 0; i < kMDGUIDSize; i++)
134 identifier[i] ^= ptr[i]; 151 identifier[i] ^= ptr[i];
135 ptr += kMDGUIDSize; 152 ptr += kMDGUIDSize;
136 } 153 }
154 *identifier_length = kMDGUIDSize;
137 return true; 155 return true;
138 } 156 }
139 157
140 // static 158 // static
141 bool FileID::ElfFileIdentifierFromMappedFile(const void* base, 159 bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
142 uint8_t identifier[kMDGUIDSize]) { 160 uint8_t identifier[kMaxBuildID],
161 size_t* identifier_length) {
143 // Look for a build id note first. 162 // Look for a build id note first.
144 if (FindElfBuildIDNote(base, identifier)) 163 if (FindElfBuildIDNote(base, identifier, identifier_length))
145 return true; 164 return true;
146 165
147 // Fall back on hashing the first page of the text section. 166 // Fall back on hashing the first page of the text section.
148 return HashElfTextSection(base, identifier); 167 return HashElfTextSection(base, identifier, identifier_length);
149 } 168 }
150 169
151 bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) { 170 bool FileID::ElfFileIdentifier(uint8_t identifier[kMaxBuildID],
171 size_t* identifier_length) {
152 MemoryMappedFile mapped_file(path_.c_str(), 0); 172 MemoryMappedFile mapped_file(path_.c_str(), 0);
153 if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)? 173 if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
154 return false; 174 return false;
155 175
156 return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier); 176 return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier,
177 identifier_length);
157 } 178 }
158 179
159 // static 180 // static
160 void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize], 181 void FileID::ConvertIdentifierToString(const uint8_t identifier[kMaxBuildID],
161 char* buffer, int buffer_length) { 182 char* buffer, int buffer_length) {
162 uint8_t identifier_swapped[kMDGUIDSize]; 183 uint8_t identifier_swapped[kMDGUIDSize];
163 184
164 // Endian-ness swap to match dump processor expectation. 185 // Endian-ness swap to match dump processor expectation.
165 memcpy(identifier_swapped, identifier, kMDGUIDSize); 186 memcpy(identifier_swapped, identifier, kMDGUIDSize);
166 uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped); 187 uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
167 *data1 = htonl(*data1); 188 *data1 = htonl(*data1);
168 uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4); 189 uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
169 *data2 = htons(*data2); 190 *data2 = htons(*data2);
170 uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6); 191 uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
(...skipping 11 matching lines...) Expand all
182 203
183 buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi; 204 buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
184 buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo; 205 buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
185 } 206 }
186 207
187 // NULL terminate 208 // NULL terminate
188 buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0; 209 buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0;
189 } 210 }
190 211
191 } // namespace google_breakpad 212 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698