Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/os/aix/loadlib_aix.cpp
40930 views
1
/*
2
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
*
6
* This code is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 only, as
8
* published by the Free Software Foundation.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*
24
*/
25
26
27
// Implementation of LoadedLibraries and friends
28
29
// Ultimately this just uses loadquery()
30
// See:
31
// http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp
32
// ?topic=/com.ibm.aix.basetechref/doc/basetrf1/loadquery.htm
33
34
#include "loadlib_aix.hpp"
35
#include "misc_aix.hpp"
36
#include "porting_aix.hpp"
37
#include "utilities/debug.hpp"
38
#include "utilities/ostream.hpp"
39
40
// For loadquery()
41
#include <sys/ldr.h>
42
43
// Use raw malloc instead of os::malloc - this code gets used for error reporting.
44
45
// A class to "intern" eternal strings.
46
// TODO: similar coding exists in AIX version of dladdr and potentially elsewhere: consolidate!
47
class StringList {
48
49
char** _list;
50
int _cap;
51
int _num;
52
53
// Enlarge list. If oom, leave old list intact and return false.
54
bool enlarge() {
55
int cap2 = _cap + 64;
56
char** l2 = (char**) ::realloc(_list, sizeof(char*) * cap2);
57
if (!l2) {
58
return false;
59
}
60
_list = l2;
61
_cap = cap2;
62
return true;
63
}
64
65
// Append string to end of list.
66
// Returns NULL if oom.
67
char* append(const char* s) {
68
if (_cap == _num) {
69
if (!enlarge()) {
70
return NULL;
71
}
72
}
73
assert0(_cap > _num);
74
char* s2 = ::strdup(s);
75
if (!s2) {
76
return NULL;
77
}
78
_list[_num] = s2;
79
trcVerbose("StringDir: added %s at pos %d", s2, _num);
80
_num ++;
81
return s2;
82
}
83
84
public:
85
86
StringList()
87
: _list(NULL)
88
, _cap(0)
89
, _num(0)
90
{}
91
92
// String is copied into the list; pointer to copy is returned.
93
// Returns NULL if oom.
94
char* add (const char* s) {
95
for (int i = 0; i < _num; i++) {
96
if (strcmp(_list[i], s) == 0) {
97
return _list[i];
98
}
99
}
100
return append(s);
101
}
102
103
};
104
105
static StringList g_stringlist;
106
107
//////////////////////
108
109
// Entries are kept in a linked list ordered by text address. Entries are not
110
// eternal - this list is rebuilt on every reload.
111
// Note that we do not hand out those entries, but copies of them.
112
113
struct entry_t {
114
entry_t* next;
115
loaded_module_t info;
116
};
117
118
static void print_entry(const entry_t* e, outputStream* os) {
119
const loaded_module_t* const lm = &(e->info);
120
os->print(" %c text: " INTPTR_FORMAT " - " INTPTR_FORMAT
121
", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " "
122
"%s",
123
(lm->is_in_vm ? '*' : ' '),
124
lm->text, (uintptr_t)lm->text + lm->text_len,
125
lm->data, (uintptr_t)lm->data + lm->data_len,
126
lm->path);
127
if (lm->member) {
128
os->print("(%s)", lm->member);
129
}
130
}
131
132
static entry_t* g_first = NULL;
133
134
static entry_t* find_entry_for_text_address(const void* p) {
135
for (entry_t* e = g_first; e; e = e->next) {
136
if ((uintptr_t)p >= (uintptr_t)e->info.text &&
137
(uintptr_t)p < ((uintptr_t)e->info.text + e->info.text_len)) {
138
return e;
139
}
140
}
141
return NULL;
142
}
143
144
static entry_t* find_entry_for_data_address(const void* p) {
145
for (entry_t* e = g_first; e; e = e->next) {
146
if ((uintptr_t)p >= (uintptr_t)e->info.data &&
147
(uintptr_t)p < ((uintptr_t)e->info.data + e->info.data_len)) {
148
return e;
149
}
150
}
151
return NULL;
152
}
153
154
// Adds a new entry to the list (ordered by text address ascending).
155
static void add_entry_to_list(entry_t* e, entry_t** start) {
156
entry_t* last = NULL;
157
entry_t* e2 = *start;
158
while (e2 && e2->info.text < e->info.text) {
159
last = e2;
160
e2 = e2->next;
161
}
162
if (last) {
163
last->next = e;
164
} else {
165
*start = e;
166
}
167
e->next = e2;
168
}
169
170
static void free_entry_list(entry_t** start) {
171
entry_t* e = *start;
172
while (e) {
173
entry_t* const e2 = e->next;
174
::free(e);
175
e = e2;
176
}
177
*start = NULL;
178
}
179
180
181
// Rebuild the internal module table. If an error occurs, old table remains
182
// unchanged.
183
static bool reload_table() {
184
185
bool rc = false;
186
187
trcVerbose("reload module table...");
188
189
entry_t* new_list = NULL;
190
const struct ld_info* ldi = NULL;
191
192
// Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. loadquery
193
// requires a large enough buffer.
194
uint8_t* buffer = NULL;
195
size_t buflen = 1024;
196
for (;;) {
197
buffer = (uint8_t*) ::realloc(buffer, buflen);
198
if (loadquery(L_GETINFO, buffer, buflen) == -1) {
199
if (errno == ENOMEM) {
200
buflen *= 2;
201
} else {
202
trcVerbose("loadquery failed (%d)", errno);
203
goto cleanup;
204
}
205
} else {
206
break;
207
}
208
}
209
210
trcVerbose("loadquery buffer size is " SIZE_FORMAT ".", buflen);
211
212
// Iterate over the loadquery result. For details see sys/ldr.h on AIX.
213
ldi = (struct ld_info*) buffer;
214
215
for (;;) {
216
217
entry_t* e = (entry_t*) ::malloc(sizeof(entry_t));
218
if (!e) {
219
trcVerbose("OOM.");
220
goto cleanup;
221
}
222
223
memset(e, 0, sizeof(entry_t));
224
225
e->info.text = ldi->ldinfo_textorg;
226
e->info.text_len = ldi->ldinfo_textsize;
227
e->info.data = ldi->ldinfo_dataorg;
228
e->info.data_len = ldi->ldinfo_datasize;
229
230
e->info.path = g_stringlist.add(ldi->ldinfo_filename);
231
if (!e->info.path) {
232
trcVerbose("OOM.");
233
goto cleanup;
234
}
235
236
// Extract short name
237
{
238
const char* p = strrchr(e->info.path, '/');
239
if (p) {
240
p ++;
241
e->info.shortname = p;
242
} else {
243
e->info.shortname = e->info.path;
244
}
245
}
246
247
// Do we have a member name as well (see ldr.h)?
248
const char* p_mbr_name =
249
ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1;
250
if (*p_mbr_name) {
251
e->info.member = g_stringlist.add(p_mbr_name);
252
if (!e->info.member) {
253
trcVerbose("OOM.");
254
goto cleanup;
255
}
256
} else {
257
e->info.member = NULL;
258
}
259
260
if (strcmp(e->info.shortname, "libjvm.so") == 0) {
261
// Note that this, theoretically, is fuzzy. We may accidentally contain
262
// more than one libjvm.so. But that is improbable, so lets go with this
263
// solution.
264
e->info.is_in_vm = true;
265
}
266
267
trcVerbose("entry: %p " SIZE_FORMAT ", %p " SIZE_FORMAT ", %s %s %s, %d",
268
e->info.text, e->info.text_len,
269
e->info.data, e->info.data_len,
270
e->info.path, e->info.shortname,
271
(e->info.member ? e->info.member : "NULL"),
272
e->info.is_in_vm
273
);
274
275
// Add to list.
276
add_entry_to_list(e, &new_list);
277
278
// Next entry...
279
if (ldi->ldinfo_next) {
280
ldi = (struct ld_info*)(((char*)ldi) + ldi->ldinfo_next);
281
} else {
282
break;
283
}
284
}
285
286
// We are done. All is well. Free old list and swap to new one.
287
if (g_first) {
288
free_entry_list(&g_first);
289
}
290
g_first = new_list;
291
new_list = NULL;
292
293
rc = true;
294
295
cleanup:
296
297
if (new_list) {
298
free_entry_list(&new_list);
299
}
300
301
::free(buffer);
302
303
return rc;
304
305
} // end LoadedLibraries::reload()
306
307
308
///////////////////////////////////////////////////////////////////////////////
309
// Externals
310
311
static MiscUtils::CritSect g_cs;
312
313
// Rebuild the internal module table. If an error occurs, old table remains
314
// unchanged.
315
bool LoadedLibraries::reload() {
316
MiscUtils::AutoCritSect lck(&g_cs);
317
return reload_table();
318
}
319
320
void LoadedLibraries::print(outputStream* os) {
321
MiscUtils::AutoCritSect lck(&g_cs);
322
if (!g_first) {
323
reload_table();
324
}
325
for (entry_t* e = g_first; e; e = e->next) {
326
print_entry(e, os);
327
os->cr();
328
}
329
}
330
331
bool LoadedLibraries::find_for_text_address(const void* p,
332
loaded_module_t* info) {
333
MiscUtils::AutoCritSect lck(&g_cs);
334
if (!g_first) {
335
reload_table();
336
}
337
const entry_t* const e = find_entry_for_text_address(p);
338
if (e) {
339
if (info) {
340
*info = e->info;
341
}
342
return true;
343
}
344
return false;
345
}
346
347
348
bool LoadedLibraries::find_for_data_address (
349
const void* p,
350
loaded_module_t* info // optional. can be NULL:
351
) {
352
MiscUtils::AutoCritSect lck(&g_cs);
353
if (!g_first) {
354
reload_table();
355
}
356
const entry_t* const e = find_entry_for_data_address(p);
357
if (e) {
358
if (info) {
359
*info = e->info;
360
}
361
return true;
362
}
363
return false;
364
}
365
366
367