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

Side by Side Diff: third_party/tcmalloc/chromium/src/base/vdso_support.cc

Issue 9311003: Update the tcmalloc chromium branch to r144 (gperftools 2.0), and merge chromium-specific changes. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Rebasec Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2008, Google Inc. 1 // Copyright (c) 2008, 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 25 matching lines...) Expand all
36 // 36 //
37 37
38 #include "base/vdso_support.h" 38 #include "base/vdso_support.h"
39 39
40 #ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h 40 #ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h
41 41
42 #include <fcntl.h> 42 #include <fcntl.h>
43 #include <stddef.h> // for std::ptrdiff_t 43 #include <stddef.h> // for std::ptrdiff_t
44 44
45 #include "base/atomicops.h" // for MemoryBarrier 45 #include "base/atomicops.h" // for MemoryBarrier
46 #include "base/linux_syscall_support.h"
46 #include "base/logging.h" 47 #include "base/logging.h"
47 #include "base/linux_syscall_support.h"
48 #include "base/dynamic_annotations.h" 48 #include "base/dynamic_annotations.h"
49 #include "base/basictypes.h" // for COMPILE_ASSERT 49 #include "base/basictypes.h" // for COMPILE_ASSERT
50 50
51 using base::subtle::MemoryBarrier; 51 using base::subtle::MemoryBarrier;
52 52
53 #ifndef AT_SYSINFO_EHDR 53 #ifndef AT_SYSINFO_EHDR
54 #define AT_SYSINFO_EHDR 33 54 #define AT_SYSINFO_EHDR 33
55 #endif 55 #endif
56 56
57 // From binutils/include/elf/common.h (this doesn't appear to be documented
58 // anywhere else).
59 //
60 // /* This flag appears in a Versym structure. It means that the symbol
61 // is hidden, and is only visible with an explicit version number.
62 // This is a GNU extension. */
63 // #define VERSYM_HIDDEN 0x8000
64 //
65 // /* This is the mask for the rest of the Versym information. */
66 // #define VERSYM_VERSION 0x7fff
67
68 #define VERSYM_VERSION 0x7fff
69
70 namespace base { 57 namespace base {
71 58
72 namespace { 59 const void *VDSOSupport::vdso_base_ = ElfMemImage::kInvalidBase;
73 template <int N> class ElfClass {
74 public:
75 static const int kElfClass = -1;
76 static int ElfBind(const ElfW(Sym) *) {
77 CHECK(false); // << "Unexpected word size";
78 return 0;
79 }
80 static int ElfType(const ElfW(Sym) *) {
81 CHECK(false); // << "Unexpected word size";
82 return 0;
83 }
84 };
85
86 template <> class ElfClass<32> {
87 public:
88 static const int kElfClass = ELFCLASS32;
89 static int ElfBind(const ElfW(Sym) *symbol) {
90 return ELF32_ST_BIND(symbol->st_info);
91 }
92 static int ElfType(const ElfW(Sym) *symbol) {
93 return ELF32_ST_TYPE(symbol->st_info);
94 }
95 };
96
97 template <> class ElfClass<64> {
98 public:
99 static const int kElfClass = ELFCLASS64;
100 static int ElfBind(const ElfW(Sym) *symbol) {
101 return ELF64_ST_BIND(symbol->st_info);
102 }
103 static int ElfType(const ElfW(Sym) *symbol) {
104 return ELF64_ST_TYPE(symbol->st_info);
105 }
106 };
107
108 typedef ElfClass<__WORDSIZE> CurrentElfClass;
109
110 // Extract an element from one of the ELF tables, cast it to desired type.
111 // This is just a simple arithmetic and a glorified cast.
112 // Callers are responsible for bounds checking.
113 template <class T>
114 const T* GetTableElement(const ElfW(Ehdr) *ehdr,
115 ElfW(Off) table_offset,
116 ElfW(Word) element_size,
117 size_t index) {
118 return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr)
119 + table_offset
120 + index * element_size);
121 }
122 } // namespace
123
124 const void *const VDSOSupport::kInvalidBase =
125 reinterpret_cast<const void *>(~0L);
126
127 const void *VDSOSupport::vdso_base_ = kInvalidBase;
128 VDSOSupport::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU; 60 VDSOSupport::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU;
129
130 VDSOSupport::ElfMemImage::ElfMemImage(const void *base) {
131 CHECK(base != kInvalidBase);
132 Init(base);
133 }
134
135 int VDSOSupport::ElfMemImage::GetNumSymbols() const {
136 if (!hash_) {
137 return 0;
138 }
139 // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash
140 return hash_[1];
141 }
142
143 const ElfW(Sym) *VDSOSupport::ElfMemImage::GetDynsym(int index) const {
144 CHECK_LT(index, GetNumSymbols());
145 return dynsym_ + index;
146 }
147
148 const ElfW(Versym) *VDSOSupport::ElfMemImage::GetVersym(int index) const {
149 CHECK_LT(index, GetNumSymbols());
150 return versym_ + index;
151 }
152
153 const ElfW(Phdr) *VDSOSupport::ElfMemImage::GetPhdr(int index) const {
154 CHECK_LT(index, ehdr_->e_phnum);
155 return GetTableElement<ElfW(Phdr)>(ehdr_,
156 ehdr_->e_phoff,
157 ehdr_->e_phentsize,
158 index);
159 }
160
161 const char *VDSOSupport::ElfMemImage::GetDynstr(ElfW(Word) offset) const {
162 CHECK_LT(offset, strsize_);
163 return dynstr_ + offset;
164 }
165
166 const void *VDSOSupport::ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const {
167 if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) {
168 // Symbol corresponds to "special" (e.g. SHN_ABS) section.
169 return reinterpret_cast<const void *>(sym->st_value);
170 }
171 CHECK_LT(link_base_, sym->st_value);
172 return GetTableElement<char>(ehdr_, 0, 1, sym->st_value) - link_base_;
173 }
174
175 const ElfW(Verdef) *VDSOSupport::ElfMemImage::GetVerdef(int index) const {
176 CHECK_LE(index, verdefnum_);
177 const ElfW(Verdef) *version_definition = verdef_;
178 while (version_definition->vd_ndx < index && version_definition->vd_next) {
179 const char *const version_definition_as_char =
180 reinterpret_cast<const char *>(version_definition);
181 version_definition =
182 reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char +
183 version_definition->vd_next);
184 }
185 return version_definition->vd_ndx == index ? version_definition : NULL;
186 }
187
188 const ElfW(Verdaux) *VDSOSupport::ElfMemImage::GetVerdefAux(
189 const ElfW(Verdef) *verdef) const {
190 return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1);
191 }
192
193 const char *VDSOSupport::ElfMemImage::GetVerstr(ElfW(Word) offset) const {
194 CHECK_LT(offset, strsize_);
195 return dynstr_ + offset;
196 }
197
198 void VDSOSupport::ElfMemImage::Init(const void *base) {
199 ehdr_ = NULL;
200 dynsym_ = NULL;
201 dynstr_ = NULL;
202 versym_ = NULL;
203 verdef_ = NULL;
204 hash_ = NULL;
205 strsize_ = 0;
206 verdefnum_ = 0;
207 link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this.
208 if (!base) {
209 return;
210 }
211 const intptr_t base_as_uintptr_t = reinterpret_cast<uintptr_t>(base);
212 // Fake VDSO has low bit set.
213 const bool fake_vdso = ((base_as_uintptr_t & 1) != 0);
214 base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1);
215 const char *const base_as_char = reinterpret_cast<const char *>(base);
216 if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 ||
217 base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) {
218 RAW_DCHECK(false, "no ELF magic"); // at %p", base);
219 return;
220 }
221 int elf_class = base_as_char[EI_CLASS];
222 if (elf_class != CurrentElfClass::kElfClass) {
223 DCHECK_EQ(elf_class, CurrentElfClass::kElfClass);
224 return;
225 }
226 switch (base_as_char[EI_DATA]) {
227 case ELFDATA2LSB: {
228 if (__LITTLE_ENDIAN != __BYTE_ORDER) {
229 DCHECK_EQ(__LITTLE_ENDIAN, __BYTE_ORDER); // << ": wrong byte order";
230 return;
231 }
232 break;
233 }
234 case ELFDATA2MSB: {
235 if (__BIG_ENDIAN != __BYTE_ORDER) {
236 DCHECK_EQ(__BIG_ENDIAN, __BYTE_ORDER); // << ": wrong byte order";
237 return;
238 }
239 break;
240 }
241 default: {
242 RAW_DCHECK(false, "unexpected data encoding"); // << base_as_char[EI_DATA] ;
243 return;
244 }
245 }
246
247 ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base);
248 const ElfW(Phdr) *dynamic_program_header = NULL;
249 for (int i = 0; i < ehdr_->e_phnum; ++i) {
250 const ElfW(Phdr) *const program_header = GetPhdr(i);
251 switch (program_header->p_type) {
252 case PT_LOAD:
253 if (link_base_ == ~0L) {
254 link_base_ = program_header->p_vaddr;
255 }
256 break;
257 case PT_DYNAMIC:
258 dynamic_program_header = program_header;
259 break;
260 }
261 }
262 if (link_base_ == ~0L || !dynamic_program_header) {
263 RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO");
264 RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO");
265 // Mark this image as not present. Can not recur infinitely.
266 Init(0);
267 return;
268 }
269 std::ptrdiff_t relocation =
270 base_as_char - reinterpret_cast<const char *>(link_base_);
271 ElfW(Dyn) *dynamic_entry =
272 reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr +
273 relocation);
274 for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {
275 ElfW(Xword) value = dynamic_entry->d_un.d_val;
276 if (fake_vdso) {
277 // A complication: in the real VDSO, dynamic entries are not relocated
278 // (it wasn't loaded by a dynamic loader). But when testing with a
279 // "fake" dlopen()ed vdso library, the loader relocates some (but
280 // not all!) of them before we get here.
281 if (dynamic_entry->d_tag == DT_VERDEF) {
282 // The only dynamic entry (of the ones we care about) libc-2.3.6
283 // loader doesn't relocate.
284 value += relocation;
285 }
286 } else {
287 // Real VDSO. Everything needs to be relocated.
288 value += relocation;
289 }
290 switch (dynamic_entry->d_tag) {
291 case DT_HASH:
292 hash_ = reinterpret_cast<ElfW(Word) *>(value);
293 break;
294 case DT_SYMTAB:
295 dynsym_ = reinterpret_cast<ElfW(Sym) *>(value);
296 break;
297 case DT_STRTAB:
298 dynstr_ = reinterpret_cast<const char *>(value);
299 break;
300 case DT_VERSYM:
301 versym_ = reinterpret_cast<ElfW(Versym) *>(value);
302 break;
303 case DT_VERDEF:
304 verdef_ = reinterpret_cast<ElfW(Verdef) *>(value);
305 break;
306 case DT_VERDEFNUM:
307 verdefnum_ = dynamic_entry->d_un.d_val;
308 break;
309 case DT_STRSZ:
310 strsize_ = dynamic_entry->d_un.d_val;
311 break;
312 default:
313 // Unrecognized entries explicitly ignored.
314 break;
315 }
316 }
317 if (!hash_ || !dynsym_ || !dynstr_ || !versym_ ||
318 !verdef_ || !verdefnum_ || !strsize_) {
319 RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)");
320 RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)");
321 RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)");
322 RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)");
323 RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)");
324 RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)");
325 RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)");
326 // Mark this image as not present. Can not recur infinitely.
327 Init(0);
328 return;
329 }
330 }
331
332 VDSOSupport::VDSOSupport() 61 VDSOSupport::VDSOSupport()
333 // If vdso_base_ is still set to kInvalidBase, we got here 62 // If vdso_base_ is still set to kInvalidBase, we got here
334 // before VDSOSupport::Init has been called. Call it now. 63 // before VDSOSupport::Init has been called. Call it now.
335 : image_(vdso_base_ == kInvalidBase ? Init() : vdso_base_) { 64 : image_(vdso_base_ == ElfMemImage::kInvalidBase ? Init() : vdso_base_) {
336 } 65 }
337 66
338 // NOTE: we can't use GoogleOnceInit() below, because we can be 67 // NOTE: we can't use GoogleOnceInit() below, because we can be
339 // called by tcmalloc, and none of the *once* stuff may be functional yet. 68 // called by tcmalloc, and none of the *once* stuff may be functional yet.
340 // 69 //
341 // In addition, we hope that the VDSOSupportHelper constructor 70 // In addition, we hope that the VDSOSupportHelper constructor
342 // causes this code to run before there are any threads, and before 71 // causes this code to run before there are any threads, and before
343 // InitGoogle() has executed any chroot or setuid calls. 72 // InitGoogle() has executed any chroot or setuid calls.
344 // 73 //
345 // Finally, even if there is a race here, it is harmless, because 74 // Finally, even if there is a race here, it is harmless, because
346 // the operation should be idempotent. 75 // the operation should be idempotent.
347 const void *VDSOSupport::Init() { 76 const void *VDSOSupport::Init() {
348 if (vdso_base_ == kInvalidBase) { 77 if (vdso_base_ == ElfMemImage::kInvalidBase) {
349 // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[] 78 // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
350 // on stack, and so glibc works as if VDSO was not present. 79 // on stack, and so glibc works as if VDSO was not present.
351 // But going directly to kernel via /proc/self/auxv below bypasses 80 // But going directly to kernel via /proc/self/auxv below bypasses
352 // Valgrind zapping. So we check for Valgrind separately. 81 // Valgrind zapping. So we check for Valgrind separately.
353 if (RunningOnValgrind()) { 82 if (RunningOnValgrind()) {
354 vdso_base_ = NULL; 83 vdso_base_ = NULL;
355 getcpu_fn_ = &GetCPUViaSyscall; 84 getcpu_fn_ = &GetCPUViaSyscall;
356 return NULL; 85 return NULL;
357 } 86 }
358 int fd = open("/proc/self/auxv", O_RDONLY); 87 int fd = open("/proc/self/auxv", O_RDONLY);
359 if (fd == -1) { 88 if (fd == -1) {
360 // Kernel too old to have a VDSO. 89 // Kernel too old to have a VDSO.
361 vdso_base_ = NULL; 90 vdso_base_ = NULL;
362 getcpu_fn_ = &GetCPUViaSyscall; 91 getcpu_fn_ = &GetCPUViaSyscall;
363 return NULL; 92 return NULL;
364 } 93 }
365 ElfW(auxv_t) aux; 94 ElfW(auxv_t) aux;
366 while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) { 95 while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {
367 if (aux.a_type == AT_SYSINFO_EHDR) { 96 if (aux.a_type == AT_SYSINFO_EHDR) {
368 COMPILE_ASSERT(sizeof(vdso_base_) == sizeof(aux.a_un.a_val), 97 COMPILE_ASSERT(sizeof(vdso_base_) == sizeof(aux.a_un.a_val),
369 unexpected_sizeof_pointer_NE_sizeof_a_val); 98 unexpected_sizeof_pointer_NE_sizeof_a_val);
370 vdso_base_ = reinterpret_cast<void *>(aux.a_un.a_val); 99 vdso_base_ = reinterpret_cast<void *>(aux.a_un.a_val);
371 break; 100 break;
372 } 101 }
373 } 102 }
374 close(fd); 103 close(fd);
375 if (vdso_base_ == kInvalidBase) { 104 if (vdso_base_ == ElfMemImage::kInvalidBase) {
376 // Didn't find AT_SYSINFO_EHDR in auxv[]. 105 // Didn't find AT_SYSINFO_EHDR in auxv[].
377 vdso_base_ = NULL; 106 vdso_base_ = NULL;
378 } 107 }
379 } 108 }
380 GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present. 109 GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present.
381 if (vdso_base_) { 110 if (vdso_base_) {
382 VDSOSupport vdso; 111 VDSOSupport vdso;
383 SymbolInfo info; 112 SymbolInfo info;
384 if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { 113 if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) {
385 // Casting from an int to a pointer is not legal C++. To emphasize 114 // Casting from an int to a pointer is not legal C++. To emphasize
386 // this, we use a C-style cast rather than a C++-style cast. 115 // this, we use a C-style cast rather than a C++-style cast.
387 fn = (GetCpuFn)(info.address); 116 fn = (GetCpuFn)(info.address);
388 } 117 }
389 } 118 }
390 // Subtle: this code runs outside of any locks; prevent compiler 119 // Subtle: this code runs outside of any locks; prevent compiler
391 // from assigning to getcpu_fn_ more than once. 120 // from assigning to getcpu_fn_ more than once.
392 base::subtle::MemoryBarrier(); 121 base::subtle::MemoryBarrier();
393 getcpu_fn_ = fn; 122 getcpu_fn_ = fn;
394 return vdso_base_; 123 return vdso_base_;
395 } 124 }
396 125
397 const void *VDSOSupport::SetBase(const void *base) { 126 const void *VDSOSupport::SetBase(const void *base) {
127 CHECK(base != ElfMemImage::kInvalidBase);
398 const void *old_base = vdso_base_; 128 const void *old_base = vdso_base_;
399 vdso_base_ = base; 129 vdso_base_ = base;
400 image_.Init(base); 130 image_.Init(base);
401 // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO. 131 // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO.
402 getcpu_fn_ = &InitAndGetCPU; 132 getcpu_fn_ = &InitAndGetCPU;
403 return old_base; 133 return old_base;
404 } 134 }
405 135
406 bool VDSOSupport::LookupSymbol(const char *name, 136 bool VDSOSupport::LookupSymbol(const char *name,
407 const char *version, 137 const char *version,
408 int type, 138 int type,
409 SymbolInfo *info) const { 139 SymbolInfo *info) const {
410 for (SymbolIterator it = begin(); it != end(); ++it) { 140 return image_.LookupSymbol(name, version, type, info);
411 if (strcmp(it->name, name) == 0 && strcmp(it->version, version) == 0 &&
412 CurrentElfClass::ElfType(it->symbol) == type) {
413 if (info) {
414 *info = *it;
415 }
416 return true;
417 }
418 }
419 return false;
420 } 141 }
421 142
422 bool VDSOSupport::LookupSymbolByAddress(const void *address, 143 bool VDSOSupport::LookupSymbolByAddress(const void *address,
423 SymbolInfo *info_out) const { 144 SymbolInfo *info_out) const {
424 for (SymbolIterator it = begin(); it != end(); ++it) { 145 return image_.LookupSymbolByAddress(address, info_out);
425 const char *const symbol_start =
426 reinterpret_cast<const char *>(it->address);
427 const char *const symbol_end = symbol_start + it->symbol->st_size;
428 if (symbol_start <= address && address < symbol_end) {
429 if (info_out) {
430 // Client wants to know details for that symbol (the usual case).
431 if (CurrentElfClass::ElfBind(it->symbol) == STB_GLOBAL) {
432 // Strong symbol; just return it.
433 *info_out = *it;
434 return true;
435 } else {
436 // Weak or local. Record it, but keep looking for a strong one.
437 *info_out = *it;
438 }
439 } else {
440 // Client only cares if there is an overlapping symbol.
441 return true;
442 }
443 }
444 }
445 return false;
446 }
447
448 VDSOSupport::SymbolIterator::SymbolIterator(const void *const image, int index)
449 : index_(index), image_(image) {
450 }
451
452 const VDSOSupport::SymbolInfo *VDSOSupport::SymbolIterator::operator->() const {
453 return &info_;
454 }
455
456 const VDSOSupport::SymbolInfo& VDSOSupport::SymbolIterator::operator*() const {
457 return info_;
458 }
459
460 bool VDSOSupport::SymbolIterator::operator==(const SymbolIterator &rhs) const {
461 return this->image_ == rhs.image_ && this->index_ == rhs.index_;
462 }
463
464 bool VDSOSupport::SymbolIterator::operator!=(const SymbolIterator &rhs) const {
465 return !(*this == rhs);
466 }
467
468 VDSOSupport::SymbolIterator &VDSOSupport::SymbolIterator::operator++() {
469 this->Update(1);
470 return *this;
471 }
472
473 VDSOSupport::SymbolIterator VDSOSupport::begin() const {
474 SymbolIterator it(&image_, 0);
475 it.Update(0);
476 return it;
477 }
478
479 VDSOSupport::SymbolIterator VDSOSupport::end() const {
480 return SymbolIterator(&image_, image_.GetNumSymbols());
481 }
482
483 void VDSOSupport::SymbolIterator::Update(int increment) {
484 const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_);
485 CHECK(image->IsPresent() || increment == 0);
486 if (!image->IsPresent()) {
487 return;
488 }
489 index_ += increment;
490 if (index_ >= image->GetNumSymbols()) {
491 index_ = image->GetNumSymbols();
492 return;
493 }
494 const ElfW(Sym) *symbol = image->GetDynsym(index_);
495 const ElfW(Versym) *version_symbol = image->GetVersym(index_);
496 CHECK(symbol && version_symbol);
497 const char *const symbol_name = image->GetDynstr(symbol->st_name);
498 const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION;
499 const ElfW(Verdef) *version_definition = NULL;
500 const char *version_name = "";
501 if (symbol->st_shndx == SHN_UNDEF) {
502 // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and
503 // version_index could well be greater than verdefnum_, so calling
504 // GetVerdef(version_index) may trigger assertion.
505 } else {
506 version_definition = image->GetVerdef(version_index);
507 }
508 if (version_definition) {
509 // I am expecting 1 or 2 auxiliary entries: 1 for the version itself,
510 // optional 2nd if the version has a parent.
511 CHECK_LE(1, version_definition->vd_cnt);
512 CHECK_LE(version_definition->vd_cnt, 2);
513 const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition);
514 version_name = image->GetVerstr(version_aux->vda_name);
515 }
516 info_.name = symbol_name;
517 info_.version = version_name;
518 info_.address = image->GetSymAddr(symbol);
519 info_.symbol = symbol;
520 } 146 }
521 147
522 // NOLINT on 'long' because this routine mimics kernel api. 148 // NOLINT on 'long' because this routine mimics kernel api.
523 long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, void *, void *) { // NOLINT 149 long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, void *, void *) { // NOLINT
524 #if defined(__NR_getcpu) 150 #if defined(__NR_getcpu)
525 return sys_getcpu(cpu, NULL, NULL); 151 return sys_getcpu(cpu, NULL, NULL);
526 #else 152 #else
527 // x86_64 never implemented sys_getcpu(), except as a VDSO call. 153 // x86_64 never implemented sys_getcpu(), except as a VDSO call.
528 errno = ENOSYS; 154 errno = ENOSYS;
529 return -1; 155 return -1;
(...skipping 24 matching lines...) Expand all
554 // ensure it here, with a global constructor of our own. This 180 // ensure it here, with a global constructor of our own. This
555 // is an allowed exception to the normal rule against non-trivial 181 // is an allowed exception to the normal rule against non-trivial
556 // global constructors. 182 // global constructors.
557 static class VDSOInitHelper { 183 static class VDSOInitHelper {
558 public: 184 public:
559 VDSOInitHelper() { VDSOSupport::Init(); } 185 VDSOInitHelper() { VDSOSupport::Init(); }
560 } vdso_init_helper; 186 } vdso_init_helper;
561 } 187 }
562 188
563 #endif // HAVE_VDSO_SUPPORT 189 #endif // HAVE_VDSO_SUPPORT
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/base/vdso_support.h ('k') | third_party/tcmalloc/chromium/src/central_freelist.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698