hotspot/agent/src/os/win32/libInfo.cpp
author never
Mon, 04 May 2009 22:06:47 -0700
changeset 2744 57f0579fbe09
parent 1 489c9b5090e2
child 5547 f4b087cbb361
permissions -rw-r--r--
6837224: libsaproc.so on linux needs version of 6799141 Reviewed-by: kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
// Disable too-long symbol warnings
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
#pragma warning ( disable : 4786 )
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
#include "libInfo.hpp"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
#include "nt4internals.hpp"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
#include "isNT4.hpp"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
#include "toolHelp.hpp"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
#include <assert.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
using namespace std;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
typedef void LibInfoImplFunc(DWORD pid, vector<LibInfo>& info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
static void libInfoImplNT4(DWORD pid, vector<LibInfo>& info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
static void libInfoImplToolHelp(DWORD pid, vector<LibInfo>& info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
libInfo(DWORD pid, vector<LibInfo>& info) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
  static LibInfoImplFunc* impl = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
  if (impl == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
    // See which operating system we're on
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
    impl = (isNT4() ? &libInfoImplNT4 : &libInfoImplToolHelp);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  assert(impl != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  (*impl)(pid, info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
static ULONG
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
ModuleCount(NT4::PDEBUG_BUFFER db) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  return db->ModuleInformation ? *PULONG(db->ModuleInformation) : 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
#define MAX2(a, b) (((a) < (b)) ? (b) : (a))
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
static void
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
libInfoImplNT4(DWORD pid, vector<LibInfo>& info) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  static EnumProcessModulesFunc*   enumFunc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
  static GetModuleFileNameExFunc*  fnFunc   = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
  static GetModuleInformationFunc* infoFunc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  if (enumFunc == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
    HMODULE dll = loadPSAPIDLL();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
    enumFunc = (EnumProcessModulesFunc*)   GetProcAddress(dll, "EnumProcessModules");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
    fnFunc   = (GetModuleFileNameExFunc*)  GetProcAddress(dll, "GetModuleFileNameExA");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
    infoFunc = (GetModuleInformationFunc*) GetProcAddress(dll, "GetModuleInformation");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
    assert(enumFunc != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
    assert(fnFunc   != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
    assert(infoFunc != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  static HMODULE* mods = new HMODULE[256];
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
  static int      numMods = 256;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  if (mods == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
    mods = new HMODULE[numMods];
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
    if (mods == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
  bool done = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
  if (proc == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
    DWORD bufSize = numMods * sizeof(HMODULE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
    DWORD neededSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
    if (!(*enumFunc)(proc, mods, bufSize, &neededSize)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
      // Enum failed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
      CloseHandle(proc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
    int numFetched = neededSize / sizeof(HMODULE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
    if (numMods < numFetched) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
      // Grow buffer
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
      numMods = MAX2(numFetched, 2 * numMods);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
      delete[] mods;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
      mods = new HMODULE[numMods];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
      if (mods == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
        CloseHandle(proc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
        return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
      char filename[MAX_PATH];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
      MODULEINFO modInfo;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
      // Iterate through and fetch each one's info
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
      for (int i = 0; i < numFetched; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
        if (!(*fnFunc)(proc, mods[i], filename, MAX_PATH)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
          CloseHandle(proc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
          return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
        if (!(*infoFunc)(proc, mods[i], &modInfo, sizeof(MODULEINFO))) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
          CloseHandle(proc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
          return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
        info.push_back(LibInfo(string(filename), (void*) modInfo.lpBaseOfDll));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
      done = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  } while (!done);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  CloseHandle(proc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
libInfoImplToolHelp(DWORD pid, vector<LibInfo>& info) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
  using namespace ToolHelp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
  static Module32FirstFunc*            firstFunc    = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  static Module32NextFunc*             nextFunc     = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
  if (snapshotFunc == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
    HMODULE dll = loadDLL();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
    snapshotFunc =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
      (CreateToolhelp32SnapshotFunc*) GetProcAddress(dll,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
                                                     "CreateToolhelp32Snapshot");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
    firstFunc = (Module32FirstFunc*) GetProcAddress(dll,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
                                                    "Module32First");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
    nextFunc = (Module32NextFunc*) GetProcAddress(dll,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
                                                  "Module32Next");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
    assert(snapshotFunc != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
    assert(firstFunc    != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
    assert(nextFunc     != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPMODULE, pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
  if (snapshot == (HANDLE) -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
    // Error occurred during snapshot
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  // Iterate
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  MODULEENTRY32 module;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
  if ((*firstFunc)(snapshot, &module)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
    do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
      info.push_back(LibInfo(string(module.szExePath), (void*) module.modBaseAddr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
    } while ((*nextFunc)(snapshot, &module));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  CloseHandle(snapshot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
}