2 Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
29 #include <sys/uc_access.h>
32 #include "uwx_context.h"
33 #include "uwx_trace.h"
35 #include "uwx_self_info.h"
37 #define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */
39 void uwx_free_load_module_cache(struct uwx_self_info *info);
41 int uwx_self_init_info_block(struct uwx_env *env, struct uwx_self_info *info)
46 info->sendsig_start = __load_info->li_sendsig_txt;
47 info->sendsig_end = __load_info->li_sendsig_txt +
48 __load_info->li_sendsig_tsz;
50 info->trace = env->trace;
51 info->load_module_cache = NULL;
56 struct uwx_self_info *uwx_self_init_info(struct uwx_env *env)
58 struct uwx_self_info *info;
60 info = (struct uwx_self_info *)
61 (*env->allocate_cb)(sizeof(struct uwx_self_info));
65 uwx_self_init_info_block(env, info);
70 int uwx_self_free_info(struct uwx_self_info *info)
74 if (info->load_module_cache != NULL)
75 uwx_free_load_module_cache(info);
77 (*info->env->free_cb)((void *)info);
81 int uwx_self_init_from_sigcontext(
83 struct uwx_self_info *info,
96 info->ucontext = ucontext;
97 status = __uc_get_reason(ucontext, &reason);
99 return UWX_ERR_UCACCESS;
100 status = __uc_get_ip(ucontext, &ip);
102 return UWX_ERR_UCACCESS;
103 status = __uc_get_grs(ucontext, 12, 1, &sp, &nat);
105 return UWX_ERR_UCACCESS;
106 status = __uc_get_cfm(ucontext, &cfm);
108 return UWX_ERR_UCACCESS;
110 status = __uc_get_ar_bsp(ucontext, &bsp);
112 return UWX_ERR_UCACCESS;
113 status = __uc_get_ar_bspstore(ucontext, &info->bspstore);
115 return UWX_ERR_UCACCESS;
116 status = __uc_get_ar_ec(ucontext, &ec);
118 return UWX_ERR_UCACCESS;
120 status = __uc_get_ar(ucontext, 17, &bsp);
122 return UWX_ERR_UCACCESS;
123 status = __uc_get_ar(ucontext, 18, &info->bspstore);
125 return UWX_ERR_UCACCESS;
126 status = __uc_get_ar(ucontext, 66, &ec);
128 return UWX_ERR_UCACCESS;
130 /* The returned bsp needs to be adjusted. */
131 /* For interrupt frames, where bsp was advanced by a cover */
132 /* instruction, subtract sof (size of frame). For non-interrupt */
133 /* frames, where bsp was advanced by br.call, subtract sol */
134 /* (size of locals). */
136 adj = (unsigned int)cfm & 0x7f; /* interrupt frame */
138 adj = ((unsigned int)cfm >> 7) & 0x7f; /* non-interrupt frame */
139 bsp = uwx_add_to_bsp(bsp, -adj);
141 uwx_init_context(env, ip, sp, bsp, cfm);
145 int uwx_self_do_context_frame(
147 struct uwx_self_info *info)
153 abi_context = uwx_get_abi_context_code(env);
154 if (abi_context != UWX_ABI_HPUX_SIGCONTEXT)
155 return UWX_SELF_ERR_BADABICONTEXT;
156 status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext);
157 if (status != UWX_OK)
159 return uwx_self_init_from_sigcontext(env, info,
160 (ucontext_t *)(intptr_t)ucontext);
173 struct uwx_self_info *info = (struct uwx_self_info *) tok;
179 dp = (uint64_t *) loc;
182 case UWX_COPYIN_UINFO:
183 case UWX_COPYIN_MSTACK:
185 wp = (unsigned long *) loc;
186 *wp = *(unsigned long *)(intptr_t)rem;
187 TRACE_SELF_COPYIN4(rem, len, wp)
191 *dp = *(uint64_t *)(intptr_t)rem;
192 TRACE_SELF_COPYIN8(rem, len, dp)
196 case UWX_COPYIN_RSTACK:
198 if (info->ucontext == 0 && rem == (info->bspstore | 0x1f8)) {
199 *dp = info->env->context.special[UWX_REG_AR_RNAT];
202 else if (info->ucontext == 0 || rem < info->bspstore) {
203 *dp = *(uint64_t *)(intptr_t)rem;
204 TRACE_SELF_COPYIN8(rem, len, dp)
208 status = __uc_get_rsebs(info->ucontext,
209 (uint64_t *)(intptr_t)rem, 1, dp);
215 if (info->ucontext != 0) {
217 if (rem == UWX_REG_PREDS)
218 status = __uc_get_prs(info->ucontext, dp);
219 else if (rem == UWX_REG_AR_PFS)
220 status = __uc_get_ar(info->ucontext, 64, dp);
221 else if (rem == UWX_REG_AR_RNAT)
222 status = __uc_get_ar(info->ucontext, 19, dp);
223 else if (rem == UWX_REG_AR_UNAT)
224 status = __uc_get_ar(info->ucontext, 36, dp);
225 else if (rem == UWX_REG_AR_FPSR)
226 status = __uc_get_ar(info->ucontext, 40, dp);
227 else if (rem == UWX_REG_AR_LC)
228 status = __uc_get_ar(info->ucontext, 65, dp);
229 else if (regid >= UWX_REG_GR(1) &&
230 regid <= UWX_REG_GR(31))
231 status = __uc_get_grs(info->ucontext,
232 regid - UWX_REG_GR(0), 1, dp, &nat);
233 else if (regid >= UWX_REG_BR(0) &&
234 regid <= UWX_REG_BR(7))
235 status = __uc_get_brs(info->ucontext,
236 regid - UWX_REG_BR(0), 1, dp);
238 else if (len == 16) {
239 if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) {
240 status = __uc_get_frs(info->ucontext,
241 regid - UWX_REG_FR(0), 1, (fp_regval_t *)dp);
252 #define MODULE_CACHE_SIZE 4
254 struct load_module_cache {
256 char *names[MODULE_CACHE_SIZE];
257 struct load_module_desc descs[MODULE_CACHE_SIZE];
258 struct uwx_symbol_cache *symbol_cache;
261 void uwx_free_load_module_cache(struct uwx_self_info *info)
265 for (i = 0; i < MODULE_CACHE_SIZE; i++) {
266 if (info->load_module_cache->names[i] != NULL)
267 (*info->env->free_cb)((void *)info->load_module_cache->names[i]);
270 if (info->load_module_cache->symbol_cache != NULL)
271 uwx_release_symbol_cache(info->env,
272 info->load_module_cache->symbol_cache);
274 (*info->env->free_cb)((void *)info->load_module_cache);
277 struct load_module_desc *uwx_get_modinfo(
278 struct uwx_self_info *info,
280 char **module_name_p)
284 struct load_module_cache *cache;
285 struct load_module_desc *desc;
288 cache = info->load_module_cache;
290 cache = (struct load_module_cache *)
291 (*info->env->allocate_cb)(sizeof(struct load_module_cache));
294 for (i = 0; i < MODULE_CACHE_SIZE; i++) {
295 desc = &cache->descs[i];
298 cache->names[i] = NULL;
301 cache->symbol_cache = NULL;
302 info->load_module_cache = cache;
304 for (i = 0; i < MODULE_CACHE_SIZE; i++) {
305 desc = &cache->descs[i];
306 if (ip >= desc->text_base && ip < desc->text_base + desc->text_size)
309 if (i >= MODULE_CACHE_SIZE) {
311 cache->clock = (cache->clock + 1) % MODULE_CACHE_SIZE;
312 desc = &cache->descs[i];
313 handle = dlmodinfo(ip, desc, sizeof(*desc), 0, 0, 0);
316 if (cache->names[i] != NULL)
317 (*info->env->free_cb)(cache->names[i]);
318 cache->names[i] = NULL;
320 if (module_name_p != NULL) {
321 if (cache->names[i] == NULL) {
322 module_name = dlgetname(desc, sizeof(*desc), 0, 0, 0);
323 if (module_name != NULL) {
324 cache->names[i] = (char *)
325 (*info->env->allocate_cb)(strlen(module_name)+1);
326 if (cache->names[i] != NULL)
327 strcpy(cache->names[i], module_name);
330 *module_name_p = cache->names[i];
335 int uwx_self_lookupip(
341 struct uwx_self_info *info = (struct uwx_self_info *) tok;
343 struct load_module_desc *desc;
344 uint64_t *unwind_base;
352 if (request == UWX_LKUP_LOOKUP) {
353 TRACE_SELF_LOOKUP(ip)
354 if (ip >= info->sendsig_start && ip < info->sendsig_end) {
357 rvec[i++] = UWX_KEY_CONTEXT;
358 rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT;
359 rvec[i++] = UWX_KEY_END;
362 return UWX_LKUP_FDESC;
365 desc = uwx_get_modinfo(info, ip, NULL);
368 unwind_base = (uint64_t *) (intptr_t) desc->unwind_base;
369 TRACE_SELF_LOOKUP_DESC(desc->text_base,
370 desc->linkage_ptr, unwind_base)
373 rvec[i++] = UWX_KEY_TBASE;
374 rvec[i++] = desc->text_base;
375 rvec[i++] = UWX_KEY_UFLAGS;
376 rvec[i++] = unwind_base[0];
377 rvec[i++] = UWX_KEY_USTART;
378 rvec[i++] = desc->text_base + unwind_base[1];
379 rvec[i++] = UWX_KEY_UEND;
380 rvec[i++] = desc->text_base + unwind_base[2];
381 rvec[i++] = UWX_KEY_GP;
382 rvec[i++] = desc->linkage_ptr;
383 rvec[i++] = UWX_KEY_END;
386 return UWX_LKUP_UTABLE;
389 else if (request == UWX_LKUP_FREE) {
392 else if (request == UWX_LKUP_MODULE) {
393 desc = uwx_get_modinfo(info, ip, &module_name);
396 if (module_name == NULL)
400 rvec[i++] = UWX_KEY_MODULE;
401 rvec[i++] = (uint64_t)(intptr_t)module_name;
402 rvec[i++] = UWX_KEY_TBASE;
403 rvec[i++] = desc->text_base;
404 rvec[i++] = UWX_KEY_END;
407 return UWX_LKUP_SYMINFO;
409 else if (request == UWX_LKUP_SYMBOLS) {
411 for (i = 0; rvec[i] != UWX_KEY_END; i += 2) {
412 if (rvec[i] == UWX_KEY_FUNCSTART)
415 desc = uwx_get_modinfo(info, ip, &module_name);
418 if (module_name == NULL)
420 status = uwx_find_symbol(info->env,
421 &info->load_module_cache->symbol_cache,
422 module_name, ip - desc->text_base,
423 &func_name, &offset);
426 rvec[i++] = UWX_KEY_MODULE;
427 rvec[i++] = (uint64_t)(intptr_t)module_name;
428 rvec[i++] = UWX_KEY_TBASE;
429 rvec[i++] = desc->text_base;
430 if (status == UWX_OK) {
431 rvec[i++] = UWX_KEY_FUNC;
432 rvec[i++] = (uint64_t)(intptr_t)func_name;
433 rvec[i++] = UWX_KEY_FUNCSTART;
434 rvec[i++] = ip - offset;
436 rvec[i++] = UWX_KEY_END;
439 return UWX_LKUP_SYMINFO;