Bug 711491. Refactor MapInfo. r=bgirard

Moves MapInfo out of platform and renames it to SharedLibrary. There will
eventually be an implementation for all major platforms.

--HG--
extra : rebase_source : c7eae4bc0f0e27f2801c4e639d7dc82b47465f0b
This commit is contained in:
Jeff Muizelaar 2011-12-15 07:31:41 -05:00
parent c7a02e442c
commit b48d6841f9
6 changed files with 190 additions and 139 deletions

View File

@ -83,6 +83,7 @@ ifneq (,$(filter Android Linux,$(OS_TARGET)))
DEFINES += -DMOZ_ENABLE_PROFILER_SPS
CPPSRCS += \
shared-libraries-linux.cc \
platform-linux.cc \
TableTicker.cpp \
$(NULL)

View File

@ -43,6 +43,7 @@
#include "nsXULAppAPI.h"
#include "nsThreadUtils.h"
#include "prenv.h"
#include "shared-libraries.h"
using std::string;
@ -156,9 +157,9 @@ public:
void ToString(string* profile)
{
// Can't be called from signal because
// get_maps calls non reentrant functions.
// getting the shared library information can call non-reentrant functions.
#ifdef ENABLE_SPS_LEAF_DATA
mMaps = getmaps(getpid());
mSharedLibraryInfo = SharedLibraryInfo::GetInfoForSelf();
#endif
*profile = "";
@ -173,9 +174,9 @@ public:
void WriteProfile(FILE* stream)
{
// Can't be called from signal because
// get_maps calls non reentrant functions.
// getting the shared library information can call non-reentrant functions.
#ifdef ENABLE_SPS_LEAF_DATA
mMaps = getmaps(getpid());
mSharedLibraryInfo = SharedLibraryInfo::GetInfoForSelf();
#endif
int oldReadPos = mReadPos;
@ -187,9 +188,9 @@ public:
}
#ifdef ENABLE_SPS_LEAF_DATA
MapInfo& getMap()
SharedLibraryInfo& getSharedLibraryInfo()
{
return mMaps;
return mSharedLibraryInfo;
}
#endif
private:
@ -200,7 +201,7 @@ private:
int mReadPos; // points to the next entry we will read to
int mEntrySize;
#ifdef ENABLE_SPS_LEAF_DATA
MapInfo mMaps;
SharedLibraryInfo mSharedLibraryInfo;
#endif
};
@ -351,11 +352,11 @@ string ProfileEntry::TagToString(Profile *profile)
if (mLeafAddress) {
bool found = false;
char tagBuff[1024];
MapInfo& maps = profile->getMap();
SharedLibraryInfo& shlibInfo = profile->getSharedLibraryInfo();
unsigned long pc = (unsigned long)mLeafAddress;
// TODO Use binary sort (STL)
for (size_t i = 0; i < maps.GetSize(); i++) {
MapEntry &e = maps.GetEntry(i);
for (size_t i = 0; i < shlibInfo.GetSize(); i++) {
SharedLibrary &e = shlibInfo.GetEntry(i);
if (pc > e.GetStart() && pc < e.GetEnd()) {
if (e.GetName()) {
found = true;
@ -381,11 +382,11 @@ void ProfileEntry::WriteTag(Profile *profile, FILE *stream)
#ifdef ENABLE_SPS_LEAF_DATA
if (mLeafAddress) {
bool found = false;
MapInfo& maps = profile->getMap();
SharedLibraryInfo& shlibInfo = profile->getSharedLibraryInfo();
unsigned long pc = (unsigned long)mLeafAddress;
// TODO Use binary sort (STL)
for (size_t i = 0; i < maps.GetSize(); i++) {
MapEntry &e = maps.GetEntry(i);
for (size_t i = 0; i < shlibInfo.GetSize(); i++) {
SharedLibrary &e = shlibInfo.GetEntry(i);
if (pc > e.GetStart() && pc < e.GetEnd()) {
if (e.GetName()) {
found = true;

View File

@ -41,9 +41,6 @@
#define SIGNAL_SAVE_PROFILE SIGUSR2
#define PATH_MAX_TOSTRING(x) #x
#define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
#if defined(__GLIBC__)
// glibc doesn't implement gettid(2).
#include <sys/syscall.h>
@ -53,61 +50,6 @@ pid_t gettid()
}
#endif
#ifdef ENABLE_SPS_LEAF_DATA
/* a crapy version of getline, because it's not included in bionic */
static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
{
char *ret;
if (!*lineptr) {
*lineptr = (char*)malloc(4096);
}
ret = fgets(*lineptr, 4096, stream);
if (!ret)
return 0;
return strlen(*lineptr);
}
MapInfo getmaps(pid_t pid)
{
MapInfo info;
char path[PATH_MAX];
snprintf(path, PATH_MAX, "/proc/%d/maps", pid);
FILE *maps = fopen(path, "r");
char *line = NULL;
int count = 0;
size_t line_size = 0;
while (maps && getline (&line, &line_size, maps) > 0) {
int ret;
//XXX: needs input sanitizing
unsigned long start;
unsigned long end;
char perm[6] = "";
unsigned long offset;
char name[PATH_MAX] = "";
ret = sscanf(line,
"%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n",
&start, &end, perm, &offset, name);
if (!strchr(perm, 'x')) {
// Ignore non executable entries
continue;
}
if (ret != 5 && ret != 4) {
LOG("Get maps line failed");
continue;
}
MapEntry entry(start, end, offset, name);
info.AddMapEntry(entry);
if (count > 10000) {
LOG("Get maps failed");
break;
}
count++;
}
free(line);
return info;
}
#endif
static Sampler* sActiveSampler = NULL;

View File

@ -24,74 +24,6 @@
typedef uint8_t* Address;
class MapEntry {
public:
MapEntry(unsigned long aStart, unsigned long aEnd, unsigned long aOffset, char *aName)
: mStart(aStart)
, mEnd(aEnd)
, mOffset(aOffset)
, mName(strdup(aName))
{}
MapEntry(const MapEntry& aEntry)
: mStart(aEntry.mStart)
, mEnd(aEntry.mEnd)
, mOffset(aEntry.mOffset)
, mName(strdup(aEntry.mName))
{}
MapEntry& operator=(const MapEntry& aEntry)
{
mStart = aEntry.mStart;
mEnd = aEntry.mEnd;
mOffset = aEntry.mOffset;
mName = strdup(aEntry.mName);
return *this;
}
~MapEntry()
{
free(mName);
}
unsigned long GetStart() { return mStart; }
unsigned long GetEnd() { return mEnd; }
char* GetName() { return mName; }
private:
explicit MapEntry() {}
unsigned long mStart;
unsigned long mEnd;
unsigned long mOffset;
char *mName;
};
class MapInfo {
public:
MapInfo() {}
void AddMapEntry(MapEntry entry)
{
mEntries.push_back(entry);
}
MapEntry& GetEntry(size_t i)
{
return mEntries[i];
}
size_t GetSize()
{
return mEntries.size();
}
private:
std::vector<MapEntry> mEntries;
};
#ifdef ENABLE_SPS_LEAF_DATA
struct MapInfo getmaps(pid_t pid);
#endif
// ----------------------------------------------------------------------------
// Mutex
//

View File

@ -0,0 +1,67 @@
#define PATH_MAX_TOSTRING(x) #x
#define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include "platform.h"
#include "shared-libraries.h"
#ifdef ENABLE_SPS_LEAF_DATA
#ifndef __GLIBC__
/* a crapy version of getline, because it's not included in bionic */
static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
{
char *ret;
if (!*lineptr) {
*lineptr = (char*)malloc(4096);
}
ret = fgets(*lineptr, 4096, stream);
if (!ret)
return 0;
return strlen(*lineptr);
}
#endif
SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
{
pid_t pid = getpid();
SharedLibraryInfo info;
char path[PATH_MAX];
snprintf(path, PATH_MAX, "/proc/%d/maps", pid);
FILE *maps = fopen(path, "r");
char *line = NULL;
int count = 0;
size_t line_size = 0;
while (maps && getline (&line, &line_size, maps) > 0) {
int ret;
//XXX: needs input sanitizing
unsigned long start;
unsigned long end;
char perm[6] = "";
unsigned long offset;
char name[PATH_MAX] = "";
ret = sscanf(line,
"%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n",
&start, &end, perm, &offset, name);
if (!strchr(perm, 'x')) {
// Ignore non executable entries
continue;
}
if (ret != 5 && ret != 4) {
LOG("Get maps line failed");
continue;
}
SharedLibrary shlib(start, end, offset, name);
info.AddSharedLibrary(shlib);
if (count > 10000) {
LOG("Get maps failed");
break;
}
count++;
}
free(line);
return info;
}
#endif

View File

@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Muizelaar <jmuizelaar@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <mozilla/StdInt.h>
class SharedLibrary {
public:
SharedLibrary(unsigned long aStart, unsigned long aEnd, unsigned long aOffset, char *aName)
: mStart(aStart)
, mEnd(aEnd)
, mOffset(aOffset)
, mName(strdup(aName))
{}
SharedLibrary(const SharedLibrary& aEntry)
: mStart(aEntry.mStart)
, mEnd(aEntry.mEnd)
, mOffset(aEntry.mOffset)
, mName(strdup(aEntry.mName))
{}
SharedLibrary& operator=(const SharedLibrary& aEntry)
{
mStart = aEntry.mStart;
mEnd = aEntry.mEnd;
mOffset = aEntry.mOffset;
mName = strdup(aEntry.mName);
return *this;
}
~SharedLibrary()
{
free(mName);
}
uintptr_t GetStart() { return mStart; }
uintptr_t GetEnd() { return mEnd; }
char* GetName() { return mName; }
private:
explicit SharedLibrary() {}
uintptr_t mStart;
uintptr_t mEnd;
uintptr_t mOffset;
char *mName;
};
class SharedLibraryInfo {
public:
static SharedLibraryInfo GetInfoForSelf();
SharedLibraryInfo() {}
void AddSharedLibrary(SharedLibrary entry)
{
mEntries.push_back(entry);
}
SharedLibrary& GetEntry(size_t i)
{
return mEntries[i];
}
size_t GetSize()
{
return mEntries.size();
}
private:
std::vector<SharedLibrary> mEntries;
};