summaryrefslogtreecommitdiff
path: root/src/base/vdso_support.cc
diff options
context:
space:
mode:
authorcsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-06-10 02:04:26 +0000
committercsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-06-10 02:04:26 +0000
commit2197cc670204c583bba3903b765c77620f349609 (patch)
treeb6d730f9bb6fb50405ed78e9e6f69903e9f6061e /src/base/vdso_support.cc
parent104bf697fbd2a0b90b5f01344ee01c8caa1745d0 (diff)
downloadgperftools-2197cc670204c583bba3903b765c77620f349609.tar.gz
Tue Jun 9 18:19:06 2009 Google Inc. <opensource@google.com>
* google-perftools: version 1.3 release * Provide our own name for memory functions: tc_malloc, etc (csilvers) * Weaken memory-alloc functions so user can override them (csilvers) * Remove meaningless delete(nothrow) and delete[](nothrow) (csilvers) * BUILD: replace clever libtcmalloc/profiler.a with a new .a (csilvers) * PORTING: improve windows port by using google spinlocks (csilvers) * PORTING: Fix RedHat 9 memory allocation in heapchecker (csilvers) * PORTING: Rename OS_WINDOWS macro to PLATFORM_WINDOWS (mbelshe) * PORTING/BUGFIX: Make sure we don't clobber GetLastError (mbelshe) * BUGFIX: get rid of useless data for callgrind (weidenrinde) * BUGFIX: Modify windows patching to deadlock sometimes (csilvers) * BUGFIX: an improved fix for hook handling during fork (csilvers) * BUGFIX: revamp profiler_unittest.sh, which was very broken (csilvers) git-svn-id: http://gperftools.googlecode.com/svn/trunk@74 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
Diffstat (limited to 'src/base/vdso_support.cc')
-rw-r--r--src/base/vdso_support.cc31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/base/vdso_support.cc b/src/base/vdso_support.cc
index c113bbc..873a8ac 100644
--- a/src/base/vdso_support.cc
+++ b/src/base/vdso_support.cc
@@ -114,6 +114,7 @@ const void *VDSOSupport::vdso_base_ = kInvalidBase;
VDSOSupport::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU;
VDSOSupport::ElfMemImage::ElfMemImage(const void *base) {
+ CHECK(base != kInvalidBase);
Init(base);
}
@@ -300,18 +301,22 @@ void VDSOSupport::ElfMemImage::Init(const void *base) {
}
}
-VDSOSupport::VDSOSupport() : image_(vdso_base_) {
+VDSOSupport::VDSOSupport()
+ // If vdso_base_ is still set to kInvalidBase, we got here
+ // before VDSOSupport::Init has been called. Call it now.
+ : image_(vdso_base_ == kInvalidBase ? Init() : vdso_base_) {
}
// NOTE: we can't use GoogleOnceInit() below, because we can be
// called by tcmalloc, and none of the *once* stuff may be functional yet.
//
-// In addition, we hope that attribute constructor (which this function has)
-// causes this code to run before there are any threads.
+// In addition, we hope that the VDSOSupportHelper constructor
+// causes this code to run before there are any threads, and before
+// InitGoogle() has executed any chroot or setuid calls.
//
// Finally, even if there is a race here, it is harmless, because
// the operation should be idempotent.
-void VDSOSupport::Init() {
+const void *VDSOSupport::Init() {
if (vdso_base_ == kInvalidBase) {
// Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
// on stack, and so glibc works as if VDSO was not present.
@@ -320,14 +325,14 @@ void VDSOSupport::Init() {
if (RunningOnValgrind()) {
vdso_base_ = NULL;
getcpu_fn_ = &GetCPUViaSyscall;
- return;
+ return NULL;
}
int fd = open("/proc/self/auxv", O_RDONLY);
if (fd == -1) {
// Kernel too old to have a VDSO.
vdso_base_ = NULL;
getcpu_fn_ = &GetCPUViaSyscall;
- return;
+ return NULL;
}
ElfW(auxv_t) aux;
while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {
@@ -358,6 +363,7 @@ void VDSOSupport::Init() {
// from assigning to getcpu_fn_ more than once.
MemoryBarrier();
getcpu_fn_ = fn;
+ return vdso_base_;
}
const void *VDSOSupport::SetBase(const void *base) {
@@ -504,6 +510,19 @@ int GetCPU(void) {
int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, NULL, NULL);
return ret_code == 0 ? cpu : ret_code;
}
+
+// We need to make sure VDSOSupport::Init() is called before
+// the main() runs, since it might do something like setuid or
+// chroot. If VDSOSupport
+// is used in any global constructor, this will happen, since
+// VDSOSupport's constructor calls Init. But if not, we need to
+// ensure it here, with a global constructor of our own. This
+// is an allowed exception to the normal rule against non-trivial
+// global constructors.
+static class VDSOInitHelper {
+ public:
+ VDSOInitHelper() { VDSOSupport::Init(); }
+} vdso_init_helper;
}
#endif // HAVE_VDSO_SUPPORT