00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <errno.h>
00048 #include <strings.h>
00049 #include <string.h>
00050
00051
00052
00053
00054 #include <fcntl.h>
00055 #include <unistd.h>
00056 #include <rld_interface.h>
00057 #include <objlist.h>
00058 #include <obj_list.h>
00059 #include <elf.h>
00060 #include <sys/types.h>
00061 #include <sys/mman.h>
00062 #include <sys/stat.h>
00063 #include <sys/unwind.h>
00064 #include <link.h>
00065 #include "unwind_consumer.h"
00066
00067
00068 __uint32_t _unwind_verbose = 0;
00069
00070
00071 __unw_table_entry_t *_unwind_table = NULL;
00072 __uint64_t _unwind_table_size = 0L;
00073
00074
00075 __unw_info_t *_unwind_info = NULL;
00076 __uint64_t _unwind_info_size = 0L;
00077
00078
00079 __unw_state_info_t *_unwind_state_stack = NULL;
00080 __uint64_t _unwind_state_stack_total_size = 0L;
00081 __uint64_t _unwind_state_stack_size = 0L;
00082
00083
00084 const __uint32_t _unw_gr_map[__UNW_MAX_GR_PRESERVED] =
00085 { 4, 5, 6, 7, 12 };
00086 const __uint32_t _unw_fr_map[__UNW_MAX_FR_PRESERVED] =
00087 { 2, 3, 4, 5, 16, 17, 18, 19, 20, 21,
00088 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
00089 const __uint32_t _unw_br_map[__UNW_MAX_BR_PRESERVED] =
00090 { 0, 1, 2, 3, 4, 5 };
00091 #if 0
00092 const __uint32_t _unw_ar_map[__UNW_MAX_AR_PRESERVED] =
00093 { 17, 18, 19, 36, 40, 64, 65 };
00094 #else
00095 const __uint32_t _unw_ar_map[__UNW_MAX_AR_PRESERVED] =
00096 { 0, 0, 1, 3, 4, 5, 7 };
00097 #endif
00098
00099
00100 static __uint32_t _unwind_initialized = 0;
00101 static __uint32_t _unwind_finalized = 0;
00102
00103 #pragma set woff 1174
00104
00105 static __uint64_t _rld_start_addr = 0L;
00106 static __uint64_t _rld_end_addr = 0L;
00107 static __uint64_t _rld_runtime_offset = 0L;
00108 static __unw_info_t *_rld_unwind_table = NULL;
00109 static __uint64_t _rld_unwind_table_size = 0L;
00110
00111
00112 static __uint64_t _xeq_start_addr = 0L;
00113 static __uint64_t _xeq_end_addr = 0L;
00114 static __uint64_t _xeq_runtime_offset = 0L;
00115 static __unw_info_t *_xeq_unwind_table = NULL;
00116 static __uint64_t _xeq_unwind_table_size = 0L;
00117 #pragma reset woff 1174
00118
00119
00120 static int (*__dbg_unwind_table_addr)(__uint64_t, __uint64_t *, __uint64_t *) = NULL;
00121 static int (*__dbg_unwind_info_addr)(__uint64_t, __uint64_t *, __uint64_t *) = NULL;
00122 static int (*__dbg_unwind_info_target_addr)(__uint64_t, __uint64_t *) = NULL;
00123 static int (*__dbg_text_segment_target_addr)(__uint64_t, __uint64_t *) = NULL;
00124 static int (*__dbg_restore_gp)(__uint64_t, __uint64_t *) = NULL;
00125 static int (*__dbg_addr_read)(__uint64_t, __uint64_t, void *) = NULL;
00126 static char *_debugger_string = "gdb";
00127
00128
00129
00130
00131
00132 void unwind_debugger_init(int (*dbg_unwind_table_addr_arg)(__uint64_t,
00133 __uint64_t *, __uint64_t *),
00134 int (*dbg_unwind_info_addr_arg)(__uint64_t,
00135 __uint64_t *, __uint64_t *),
00136 int (*dbg_unwind_info_target_addr_arg)(__uint64_t,
00137 __uint64_t *),
00138 int (*dbg_text_segment_target_addr_arg)(__uint64_t,
00139 __uint64_t *),
00140 int (*dbg_restore_gp_arg)(__uint64_t,
00141 __uint64_t *),
00142 int (*dbg_addr_read_arg)(__uint64_t,
00143 __uint64_t, void *)) {
00144 __dbg_unwind_table_addr = dbg_unwind_table_addr_arg;
00145 __dbg_unwind_info_addr = dbg_unwind_info_addr_arg;
00146 __dbg_unwind_info_target_addr = dbg_unwind_info_target_addr_arg;
00147 __dbg_text_segment_target_addr = dbg_text_segment_target_addr_arg;
00148 __dbg_restore_gp = dbg_restore_gp_arg;
00149 __dbg_addr_read = dbg_addr_read_arg;
00150 }
00151
00152
00153
00154
00155
00156 #ifndef FOR_GDB
00157
00158
00159
00160
00161
00162 static __unw_error_t unwind_get_obj_phdr( const char* name,
00163 char *dsoname,
00164 #if (_MIPS_SZPTR== 64)
00165 __uint64_t *load_address,
00166 #else
00167 __uint32_t *load_address,
00168 #endif
00169 Elf64_Phdr **phdr,
00170 Elf64_Half *phnum )
00171 {
00172 pid_t pid = getpid();
00173
00174 char mapname[ FILENAME_MAX ];
00175 char fname[ FILENAME_MAX ];
00176 __uint32_t inode, device;
00177 #if (_MIPS_SZPTR== 64)
00178 __uint64_t l_addr;
00179 #else
00180 __uint32_t l_addr;
00181 #endif
00182
00183 FILE* f;
00184 char line[5000];
00185 struct stat statf;
00186
00187 if( *name == 0 )
00188 {
00189 char exe[ FILENAME_MAX ];
00190 int len;
00191 sprintf(exe, "/proc/%d/exe", pid );
00192 len = readlink( exe, fname, FILENAME_MAX );
00193 fname[len] = 0;
00194 strcpy( dsoname, fname );
00195 }
00196 else
00197 {
00198 int len;
00199 char *slash, dirname[ FILENAME_MAX ];
00200
00201 strcpy( dirname, name );
00202 len = readlink( name, fname, FILENAME_MAX );
00203 fname[ len ] = 0;
00204 slash = strrchr( dirname, '/' );
00205 if( slash )
00206 {
00207 *slash = 0;
00208 sprintf( dsoname, "%s/%s", dirname, fname );
00209 }
00210 else
00211 strcpy( dsoname, fname );
00212 }
00213 stat( dsoname, &statf );
00214 inode = statf.st_ino;
00215 device = statf.st_dev;
00216
00217 sprintf(mapname, "/proc/%d/maps", pid );
00218 f = fopen(mapname, "r" );
00219 if( !f )
00220 return __UNW_NULL_ERROR;
00221 l_addr = 0;
00222 while( !l_addr && fgets( line, sizeof(line), f ) && !feof( f ))
00223 {
00224 __uint64_t addr, dum1, dum2;
00225 __uint32_t min, maj, in;
00226 char perm[5];
00227 if( sscanf( line, "%llx-%llx %s %llx %x:%x %d %s",
00228 &addr, &dum1, &perm, &dum2, &maj, &min, &in, fname ) )
00229 {
00230 if( in && perm[2] == 'x' )
00231 {
00232 if( inode == in && device == ((maj<<8)|min) )
00233 {
00234 l_addr = addr;
00235 }
00236 }
00237 }
00238 }
00239 fclose( f );
00240
00241 if( l_addr )
00242 {
00243 int i;
00244 Elf64_Ehdr* ehdr;
00245 ehdr = (Elf64_Ehdr*) l_addr;
00246 *phdr = (Elf64_Phdr*) ((char*) ehdr + ehdr->e_phoff);
00247 *phnum = ehdr->e_phnum;
00248 *load_address = l_addr;
00249 return __UNW_OK;
00250 }
00251 else
00252 {
00253 *phdr = NULL;
00254 *phnum = 0;
00255 *load_address = 0;
00256 return __UNW_NULL_ERROR;
00257 }
00258 }
00259
00260
00261 #endif
00262
00263
00264
00265
00266 static __unw_error_t unwind_get_obj_data(__uint64_t ip,
00267 Elf64_Ehdr **ehdr,
00268 Elf64_Phdr **phdr,
00269 __uint64_t *runtime_offset,
00270 __uint64_t *text_segment_addr) {
00271 __uint64_t i;
00272
00273 #ifndef FOR_GDB
00274 struct link_map *obj = (struct link_map *) _r_debug.r_map;
00275 __uint32_t region_found = 0;
00276
00277 if (_r_debug.r_map) {
00278 while (obj) {
00279 __uint64_t region_start = 0L, region_end = 0L;
00280 #if (_MIPS_SZPTR == 64)
00281 __uint64_t l_addr;
00282 #else
00283 __uint32_t l_addr;
00284 #endif
00285
00286 Elf64_Half phnum;
00287 char objname[ FILENAME_MAX ], *l_name;
00288 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00289 unwind_output(
00290 "unwind_get_obj_data() INTERNAL MSG: obj %s @%llx (%llx, %d) for ip = %llx",
00291 obj->l_name,
00292 obj->l_addr, obj->l_phdr, obj->l_phnum, ip );
00293 }
00294 if( !*obj->l_name
00295 || !obj->l_phdr
00296 || !obj->l_phnum
00297 )
00298 {
00299 l_name = objname;
00300 if( __UNW_OK != unwind_get_obj_phdr( obj->l_name, objname, &l_addr,
00301 phdr, &phnum ))
00302 {
00303 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00304 unwind_output("unwind_get_obj_data() ERROR: %s %s",
00305 "program header address not found for", objname );
00306 }
00307 return __UNW_INTERNAL_ERROR;
00308 }
00309 *ehdr = (Elf64_Ehdr*) l_addr;
00310
00311
00312
00313
00314
00315 }
00316 else
00317 {
00318 *phdr = (Elf64_Phdr *) obj->l_phdr;
00319 *ehdr = (Elf64_Ehdr*) obj->l_addr;
00320 phnum = obj->l_phnum;
00321 l_addr = obj->l_addr;
00322 l_name = obj->l_name;
00323 }
00324 for (i = 0; i < (__uint64_t)phnum; i++) {
00325 if ((PT_LOAD == (*phdr)[i].p_type) &&
00326 ((PF_R | PF_X) == (*phdr)[i].p_flags)) {
00327 *runtime_offset = l_addr- (__uint64_t)(*phdr)[i].p_vaddr;
00328 region_start = (__uint64_t)(*phdr)[i].p_vaddr
00329 + *runtime_offset;
00330 region_end = region_start +
00331 (__uint64_t)(*phdr)[i].p_memsz;
00332 break;
00333 }
00334 }
00335 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00336 unwind_output("%s %s %s [ 0x%llx - %llx]",
00337 "unwind_get_obj_data() INTERNAL MSG:",
00338 "DSO ", l_name,
00339 region_start, region_end );
00340 }
00341 if ((ip >= region_start) && (ip < region_end)) {
00342 *text_segment_addr = region_start;
00343 region_found = 1;
00344 break;
00345 }
00346 obj = obj->l_next;
00347 }
00348 if (!region_found) {
00349
00350 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00351 unwind_output("unwind_get_obj_data() ERROR: %s",
00352 "elf and/or program header not found");
00353 }
00354 return __UNW_INTERNAL_ERROR;
00355 }
00356 } else {
00357
00358 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00359 unwind_output("unwind_get_obj_data() ERROR: %s",
00360 "program must be static" );
00361 }
00362 }
00363 #endif // FOR_GDB
00364 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00365 unwind_output("%s %s 0x%llx for ip=0x%llx",
00366 "unwind_get_obj_data() INTERNAL MSG:",
00367 "found elf header @",
00368 #if (_MIPS_SZLONG == 32)
00369 (unsigned long long)(__uint32_t)*ehdr,
00370 #else
00371 (unsigned long long)*ehdr,
00372 #endif
00373 (unsigned long long)ip);
00374 unwind_output("%s %s 0x%llx for ip=0x%llx",
00375 "unwind_get_obj_data() INTERNAL MSG:",
00376 "found program header @",
00377 #if (_MIPS_SZLONG == 32)
00378 (unsigned long long)(__uint32_t)*phdr,
00379 #else
00380 (unsigned long long)*phdr,
00381 #endif
00382 (unsigned long long)ip);
00383 unwind_output("%s %s 0x%llx for ip=0x%llx",
00384 "unwind_get_obj_data() INTERNAL MSG:",
00385 "found text segment addr @",
00386 (unsigned long long)*text_segment_addr,
00387 (unsigned long long)ip);
00388 unwind_output("%s %s 0x%llx for ip=0x%llx",
00389 "unwind_get_obj_data() INTERNAL MSG:",
00390 "found runtime offset =",
00391 (unsigned long long)*runtime_offset,
00392 (unsigned long long)ip);
00393 }
00394
00395 return __UNW_OK;
00396 }
00397
00398
00399
00400
00401
00402 static __unw_error_t unwind_get_unwind_table_data(__uint64_t ip,
00403 __uint64_t *unwind_table_addr,
00404 __uint64_t *unwind_table_size,
00405 __uint64_t *text_segment_addr) {
00406 Elf64_Ehdr *ehdr;
00407 Elf64_Phdr *phdr;
00408 __unw_error_t ret;
00409 __uint64_t i, runtime_offset;
00410
00411
00412
00413
00414 if (__UNW_OK != (ret = unwind_get_obj_data(ip, &ehdr, &phdr,
00415 &runtime_offset, text_segment_addr))) {
00416 return ret;
00417 }
00418
00419
00420 for (i = 0; i < (__uint64_t)ehdr->e_phnum; i++) {
00421 unwind_output("[%d] type = %x\n", i, phdr[i].p_type );
00422 if (PT_IA64_UNWIND == phdr[i].p_type) {
00423 *unwind_table_addr = (__uint64_t)phdr[i].p_vaddr;
00424 *unwind_table_addr += runtime_offset;
00425 *unwind_table_size = (__uint64_t)phdr[i].p_memsz;
00426 break;
00427 }
00428 }
00429 if ((__uint64_t)ehdr->e_phnum == i) {
00430 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00431 unwind_output("unwind_get_unwind_table_data() ERROR: %s",
00432 ".IA64.unwind section not found");
00433 }
00434 return __UNW_INTERNAL_ERROR;
00435 }
00436
00437 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00438 unwind_output("%s %s 0x%llx %s %llu*%u for ip=0x%llx",
00439 "unwind_get_unwind_table_data() INTERNAL MSG:",
00440 "found unwind table @",
00441 (unsigned long long)*unwind_table_addr,
00442 "with size of",
00443 (unsigned long long)((*unwind_table_size) /
00444 sizeof(__unw_table_entry_t)),
00445 sizeof(__unw_table_entry_t),
00446 (unsigned long long)ip);
00447 }
00448
00449 return __UNW_OK;
00450 }
00451
00452
00453
00454
00455 static __unw_error_t unwind_restore_gp(__uint64_t ip,
00456 __uint64_t *gp) {
00457 Elf64_Ehdr *ehdr;
00458 Elf64_Phdr *phdr;
00459 Elf64_Dyn *dynptr;
00460 __unw_error_t ret;
00461 __uint64_t i, dyn_addr, runtime_offset, text_segment_addr;
00462
00463
00464
00465
00466 if (__UNW_OK != (ret = unwind_get_obj_data(ip, &ehdr, &phdr,
00467 &runtime_offset, &text_segment_addr))) {
00468 return ret;
00469 }
00470
00471
00472 for (i = 0; i < (__uint64_t)ehdr->e_phnum; i++) {
00473 if (PT_DYNAMIC == phdr[i].p_type) {
00474 dyn_addr = (__uint64_t)phdr[i].p_vaddr;
00475 dyn_addr += runtime_offset;
00476 break;
00477 }
00478 }
00479 if ((__uint64_t)ehdr->e_phnum == i) {
00480 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00481 unwind_output("unwind_restore_gp() ERROR: %s",
00482 ".dynamic section not found");
00483 }
00484 return __UNW_INTERNAL_ERROR;
00485 }
00486
00487
00488 #if (_MIPS_SZLONG == 32)
00489 for (dynptr = (Elf64_Dyn *)(__uint32_t)dyn_addr; DT_NULL != dynptr->d_tag; dynptr++) {
00490 #else
00491 for (dynptr = (Elf64_Dyn *)dyn_addr; DT_NULL != dynptr->d_tag; dynptr++) {
00492 #endif
00493
00494 if (DT_MIPS_GP_VALUE == dynptr->d_tag) {
00495 *gp = (__uint64_t)dynptr->d_un.d_ptr;
00496 *gp += runtime_offset;
00497 break;
00498 }
00499 }
00500 if (DT_NULL == dynptr->d_tag) {
00501 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00502 unwind_output("unwind_restore_gp() ERROR: %s",
00503 "gp address not found");
00504 }
00505 return __UNW_INTERNAL_ERROR;
00506 }
00507
00508 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00509 unwind_output("%s %s 0x%llx for ip=0x%llx",
00510 "unwind_restore_gp() INTERNAL MSG:",
00511 "found gp @",
00512 (unsigned long long)*gp,
00513 (unsigned long long)ip);
00514 }
00515
00516 return __UNW_OK;
00517 }
00518
00519
00520
00521
00522 static int unwind_table_entry_compare(const void *ptr1, const void *ptr2) {
00523 __unw_table_entry_t *t1 = (__unw_table_entry_t *)ptr1;
00524 __unw_table_entry_t *t2 = (__unw_table_entry_t *)ptr2;
00525
00526 unwind_output("unwind_table_entry_compare: comparing t1 %p and t2 %p\n", t1, t2 );
00527 unwind_output("unwind_table_entry_compare: comparing t1 (%llx, %llx) and t2 (%llx, %llx )\n",
00528 t1->_start, t1->_end,
00529 t2->_start, t2->_end );
00530 if (t1->_start == t1->_end) {
00531 if ((t1->_start >= t2->_start) && (t1->_end < t2->_end)) {
00532 return 0;
00533 } else if (t1->_end < t2->_start) {
00534 return -1;
00535 } else {
00536 return 1;
00537 }
00538 } else {
00539 if ((t2->_start >= t1->_start) && (t2->_end < t1->_end)) {
00540 return 0;
00541 } else if (t2->_end < t1->_start) {
00542 return -1;
00543 } else {
00544 return 1;
00545 }
00546 }
00547 }
00548
00549
00550
00551
00552 __unw_error_t unwind_state_stack_pop(__uint64_t num) {
00553
00554
00555 if (NULL == _unwind_state_stack) {
00556 return __UNW_NULL_ERROR;
00557 }
00558
00559
00560 if (num > _unwind_state_stack_size) {
00561 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00562 unwind_output("unwind_state_stack_pop() ERROR: %s (%llu,%llu)",
00563 "too many elements to pop",
00564 (unsigned long long)num,
00565 (unsigned long long)_unwind_state_stack_size);
00566 }
00567 return __UNW_INV_ARG_ERROR;
00568 }
00569
00570
00571 _unwind_state_stack_size -= num;
00572
00573 return __UNW_OK;
00574 }
00575
00576
00577
00578
00579 __unw_error_t unwind_state_stack_push(__unw_state_info_t **ptr) {
00580 __unw_state_info_t *prev_unwind_state_stack;
00581 int dzfd;
00582
00583
00584 if (NULL == _unwind_state_stack) {
00585 return __UNW_NULL_ERROR;
00586 }
00587
00588
00589 if (_unwind_state_stack_total_size - 1 == _unwind_state_stack_size) {
00590 prev_unwind_state_stack = _unwind_state_stack;
00591
00592
00593 if (NULL == _unwind_state_stack) {
00594 _unwind_state_stack_total_size *= 2;
00595 if (-1 == (dzfd = open("/dev/zero", O_RDONLY))) {
00596 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00597 unwind_output("unwind_state_stack_push() ERROR: %s (errno=%d)",
00598 "open() failed",
00599 errno);
00600 }
00601 return __UNW_SYSCALL_ERROR;
00602 }
00603 if (NULL == (_unwind_state_stack =
00604 (__unw_state_info_t *)mmap(NULL,
00605 (size_t)(_unwind_state_stack_total_size *
00606 sizeof(__unw_state_info_t)),
00607 PROT_READ|PROT_WRITE,
00608 MAP_PRIVATE, dzfd,
00609 (off_t)0))) {
00610 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00611 unwind_output("unwind_state_stack_push() ERROR: %s (errno=%d)",
00612 "mmap() failed",
00613 errno);
00614 }
00615 return __UNW_MMAP_ERROR;
00616 }
00617 close(dzfd);
00618 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00619 unwind_output("%s re-mmaped _unwind_state_stack @ 0x%llx, total_size=%llu*%u",
00620 "unwind_state_stack_push() INTERNAL MSG:",
00621 #if (_MIPS_SZLONG == 32)
00622 (unsigned long long)(__uint32_t)_unwind_state_stack,
00623 #else
00624 (unsigned long long)_unwind_state_stack,
00625 #endif
00626 (unsigned long long)_unwind_state_stack_total_size,
00627 sizeof(__unw_state_info_t));
00628 }
00629 }
00630
00631
00632 bcopy((const void *)prev_unwind_state_stack, (void *)_unwind_state_stack,
00633 (size_t)((_unwind_state_stack_total_size/2) * sizeof(__unw_state_info_t)));
00634
00635
00636 munmap((void *)prev_unwind_state_stack,
00637 (size_t)((_unwind_state_stack_total_size/2) *
00638 sizeof(__unw_state_info_t)));
00639 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00640 unwind_output("%s munmapped previous _unwind_state_stack @ 0x%llx",
00641 "unwind_state_stack_push() INTERNAL MSG:",
00642 #if (_MIPS_SZLONG == 32)
00643 (unsigned long long)(__uint32_t)prev_unwind_state_stack);
00644 #else
00645 (unsigned long long)prev_unwind_state_stack);
00646 #endif
00647 }
00648 }
00649
00650
00651 if (_unwind_state_stack_size) {
00652 bcopy((const void *)&_unwind_state_stack[_unwind_state_stack_size-1],
00653 (void *)&_unwind_state_stack[_unwind_state_stack_size],
00654 (size_t)sizeof(__unw_state_info_t));
00655 } else {
00656 bzero((void *)&_unwind_state_stack[_unwind_state_stack_size],
00657 (size_t)sizeof(__unw_state_info_t));
00658 }
00659 *ptr = &_unwind_state_stack[_unwind_state_stack_size++];
00660
00661 return __UNW_OK;
00662 }
00663
00664
00665
00666
00667 __unw_error_t unwind_state_stack_top(__unw_state_info_t **ptr) {
00668
00669
00670 if (NULL == _unwind_state_stack) {
00671 return __UNW_NULL_ERROR;
00672 }
00673
00674
00675 if (_unwind_state_stack_size) {
00676 *ptr = &_unwind_state_stack[_unwind_state_stack_size - 1];
00677 } else {
00678 bzero((void *)&_unwind_state_stack[_unwind_state_stack_size],
00679 (size_t)sizeof(__unw_state_info_t));
00680 *ptr = &_unwind_state_stack[_unwind_state_stack_size++];
00681 }
00682
00683 return __UNW_OK;
00684 }
00685
00686
00687
00688
00689 __unw_error_t unwind_state_stack_search(__unw_state_info_t **ptr, __uint64_t label) {
00690 __int64_t i;
00691
00692
00693 if (NULL == _unwind_state_stack) {
00694 return __UNW_NULL_ERROR;
00695 }
00696
00697
00698 for (i = _unwind_state_stack_size - 1; i >= 0; i--) {
00699 if (_unwind_state_stack[i]._label == label) {
00700 *ptr = &_unwind_state_stack[i];
00701 _unwind_state_stack_size = i + 1;
00702 return __UNW_OK;
00703 }
00704 }
00705
00706 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00707 unwind_output("unwind_state_stack_search() ERROR: %s",
00708 "element not found");
00709 }
00710 return __UNW_NOT_FOUND_ERROR;
00711 }
00712
00713
00714
00715
00716 __unw_error_t unwind_state_stack_reset(void) {
00717
00718
00719 if (NULL == _unwind_state_stack) {
00720 return __UNW_NULL_ERROR;
00721 }
00722
00723
00724 _unwind_state_stack_size = 0;
00725
00726 return __UNW_OK;
00727 }
00728
00729
00730
00731
00732 __unw_error_t unwind_init(void) {
00733 int dzfd;
00734 char *str;
00735 static int initializing = 0;
00736
00737
00738 if (initializing) {
00739 return __UNW_OK;
00740 }
00741
00742
00743 if (!_unwind_initialized) {
00744
00745
00746 initializing = 1;
00747
00748
00749 if (NULL != (str = getenv(__UNW_CONSUMER_VERBOSE_ENV_VAR))) {
00750 _unwind_verbose = atoi(str);
00751 }
00752
00753
00754 if (NULL == _unwind_state_stack) {
00755 _unwind_state_stack_total_size = __UNW_STATE_STACK_ENTRIES_SIZE;
00756 if (-1 == (dzfd = open("/dev/zero", O_RDONLY))) {
00757 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00758 unwind_output("unwind_init() ERROR: %s (errno=%d)",
00759 "open() failed",
00760 errno);
00761 }
00762 initializing = 0;
00763 return __UNW_SYSCALL_ERROR;
00764 }
00765 if (NULL == (_unwind_state_stack =
00766 (__unw_state_info_t *)mmap(NULL,
00767 (size_t)(_unwind_state_stack_total_size *
00768 sizeof(__unw_state_info_t)),
00769 PROT_READ|PROT_WRITE,
00770 MAP_PRIVATE, dzfd,
00771 (off_t)0))) {
00772 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00773 unwind_output("unwind_init() ERROR: %s (errno=%d)",
00774 "mmap() failed",
00775 errno);
00776 }
00777 initializing = 0;
00778 return __UNW_MMAP_ERROR;
00779 }
00780 close(dzfd);
00781 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00782 unwind_output("%s mmaped _unwind_state_stack @ 0x%llx, total_size=%llu*%u",
00783 "unwind_init() INTERNAL MSG:",
00784 #if (_MIPS_SZLONG == 32)
00785 (unsigned long long)(__uint32_t)_unwind_state_stack,
00786 #else
00787 (unsigned long long)_unwind_state_stack,
00788 #endif
00789 (unsigned long long)_unwind_state_stack_total_size,
00790 sizeof(__unw_state_info_t));
00791 }
00792 }
00793
00794
00795 _unwind_initialized = 1;
00796
00797
00798 initializing = 0;
00799 }
00800
00801 return __UNW_OK;
00802 }
00803
00804
00805
00806
00807 __unw_error_t unwind_fini(void) {
00808 static int finalizing = 0;
00809
00810
00811 if (finalizing) {
00812 return __UNW_OK;
00813 }
00814
00815
00816 if (!_unwind_finalized) {
00817
00818
00819 finalizing = 1;
00820
00821
00822 if (_unwind_state_stack) {
00823 munmap((void *)_unwind_state_stack,
00824 (size_t)(_unwind_state_stack_total_size *
00825 sizeof(__unw_state_info_t)));
00826 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00827 unwind_output("%s munmapped _unwind_state_stack @ 0x%llx",
00828 "unwind_fini() INTERNAL MSG:",
00829 #if (_MIPS_SZLONG == 32)
00830 (unsigned long long)(__uint32_t)_unwind_state_stack);
00831 #else
00832 (unsigned long long)_unwind_state_stack);
00833 #endif
00834 }
00835 }
00836
00837
00838 _unwind_finalized = 1;
00839
00840
00841 finalizing = 0;
00842 }
00843
00844 return __UNW_OK;
00845 }
00846
00847
00848 __unw_error_t unwind_frame(unw_sigcontext_t *scp) {
00849 __unw_error_t ret = __UNW_OK;
00850 __unw_info_t *unwind_info;
00851 __unw_table_entry_t *unwind_table, *ptr, key;
00852 __uint64_t unwind_table_addr, unwind_table_size;
00853 __uint64_t gp = 0L, text_segment_addr = 0L;
00854 #ifdef FOR_GDB
00855 __uint64_t st_loc = 0ull;
00856 __uint64_t reg_st_loc = 0ull;
00857 __uint64_t st_loc_fr = 0ull;
00858 __UNW_STRUCT_FPREG fp_reg;
00859 #else
00860 __uint64_t *stack_loc = NULL, *reg_stack_loc = NULL;
00861 __UNW_STRUCT_FPREG *st_loc_fr = NULL;
00862 #endif
00863 __uint64_t sp = 0L, psp = 0L, cfm = 0L, bsp = 0L;
00864 __uint64_t slots, preds;
00865 __unw_state_info_t state;
00866 __int32_t i;
00867 __unw_addr_t ip = (__unw_addr_t)__UNW_CONTEXT_ACCESS_IP(scp);
00868 __unw_addr_t newip;
00869 __uint64_t addr;
00870 __uint64_t unwind_info_addr, unwind_info_size, unwind_info_target_addr;
00871
00872
00873 if (!_unwind_initialized) {
00874 if (__UNW_OK != (ret = unwind_init())) {
00875 return ret;
00876 }
00877 }
00878
00879
00880 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
00881 unwind_output("%s unwinding for ip=0x%llx",
00882 "unwind_frame() MSG:",
00883 (unsigned long long)ip);
00884 }
00885
00886
00887
00888 #ifdef FOR_GDB
00889 if (!(*__dbg_unwind_table_addr)((__uint64_t)ip,
00890 &unwind_table_addr,
00891 &unwind_table_size)) {
00892 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00893 unwind_output("unwind_frame() ERROR: %s: %s",
00894 _debugger_string,
00895 "unwind table extraction failed");
00896 }
00897 return __UNW_INTERNAL_ERROR;
00898 } else {
00899 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00900 unwind_output("%s %s %s 0x%llx %s %llu*%u for ip=0x%llx",
00901 "unwind_frame() INTERNAL MSG:",
00902 _debugger_string,
00903 "found unwind table @",
00904 (unsigned long long)unwind_table_addr,
00905 "with size of",
00906 (unsigned long long)(unwind_table_size /
00907 sizeof(__unw_table_entry_t)),
00908 sizeof(__unw_table_entry_t),
00909 (unsigned long long)ip);
00910 }
00911 }
00912 if (!(*__dbg_unwind_info_addr)((__uint64_t)ip,
00913 &unwind_info_addr,
00914 &unwind_info_size)) {
00915 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00916 unwind_output("unwind_frame() ERROR: %s: %s",
00917 _debugger_string,
00918 "unwind info extraction failed");
00919 }
00920 return __UNW_INTERNAL_ERROR;
00921 } else {
00922 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00923 unwind_output("%s %s %s 0x%llx %s %llu for ip=0x%llx",
00924 "unwind_frame() INTERNAL MSG:",
00925 _debugger_string,
00926 "found unwind info @",
00927 (unsigned long long)unwind_info_addr,
00928 "with size of",
00929 (unsigned long long)unwind_info_size,
00930 (unsigned long long)ip);
00931 }
00932 }
00933 if (!(*__dbg_unwind_info_target_addr)((__uint64_t)ip,
00934 &unwind_info_target_addr)) {
00935 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00936 unwind_output("unwind_frame() ERROR: %s: %s",
00937 _debugger_string,
00938 "unwind info target address extraction failed");
00939 }
00940 return __UNW_INTERNAL_ERROR;
00941 } else {
00942 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00943 unwind_output("%s %s %s 0x%llx for ip=0x%llx",
00944 "unwind_frame() INTERNAL MSG:",
00945 _debugger_string,
00946 "unwind info target address @",
00947 (unsigned long long)unwind_info_target_addr,
00948 (unsigned long long)ip);
00949 }
00950 }
00951 if (!(*__dbg_text_segment_target_addr)((__uint64_t)ip,
00952 &text_segment_addr)) {
00953 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00954 unwind_output("unwind_frame() ERROR: %s: %s",
00955 _debugger_string,
00956 "text segment target address extraction failed");
00957 }
00958 return __UNW_INTERNAL_ERROR;
00959 } else {
00960 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
00961 unwind_output("%s %s %s 0x%llx for ip=0x%llx",
00962 "unwind_frame() INTERNAL MSG:",
00963 _debugger_string,
00964 "text segment target address @",
00965 (unsigned long long)text_segment_addr,
00966 (unsigned long long)ip);
00967 }
00968 }
00969 #else
00970 if (__UNW_OK != (ret = unwind_get_unwind_table_data((__uint64_t)ip,
00971 &unwind_table_addr,
00972 &unwind_table_size,
00973 &text_segment_addr))) {
00974 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00975 unwind_output("unwind_frame() ERROR: %s ip=0x%llx",
00976 "can not find unwind table for runtime",
00977 (unsigned long long)ip);
00978 }
00979 return ret;
00980 }
00981 #endif
00982
00983 #if (_MIPS_SZLONG == 32)
00984 unwind_table = (__unw_table_entry_t *)(__uint32_t)unwind_table_addr;
00985 #else
00986 unwind_table = (__unw_table_entry_t *)unwind_table_addr;
00987 #endif
00988
00989
00990 ip -= (__unw_addr_t)text_segment_addr;
00991
00992
00993 key._start = key._end = ip;
00994 unwind_output("unwind_table_entry_compare: Coucou");
00995 ptr = (__unw_table_entry_t *)bsearch((const void *)&key,
00996 (const void *)unwind_table,
00997 (size_t)(unwind_table_size/sizeof(__unw_table_entry_t)),
00998 (size_t)sizeof(__unw_table_entry_t),
00999 unwind_table_entry_compare);
01000 unwind_output("unwind_table_entry_compare: Coucou");
01001
01002
01003 if (NULL == ptr) {
01004 __UNW_CONTEXT_ACCESS_IP(scp) =
01005 __UNW_CONTEXT_ACCESS_BR(scp, 0);
01006
01007 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01008 unwind_output("%s no entry in unwind table for ip=0x%llx (segment-relative)",
01009 "unwind_frame() MSG:",
01010 (unsigned long long)ip);
01011 }
01012
01013 return __UNW_OK;
01014 }
01015
01016
01017 addr = (__uint64_t)ptr->_info + text_segment_addr;
01018 #ifdef FOR_GDB
01019 addr = unwind_info_addr + (__uint64_t)ptr->_info
01020 - unwind_info_target_addr;
01021 #endif
01022 #if (_MIPS_SZLONG == 32)
01023 unwind_info = (__unw_info_t *)(__uint32_t) addr;
01024 #else
01025 unwind_info = (__unw_info_t *)addr;
01026 #endif
01027
01028
01029
01030 #if 0
01031 fprintf(stderr, "unwind_info_addr=0x%llx + 0x%llx header=0x%llx\n",
01032 unwind_info_addr, (__uint64_t)ptr->_info, unwind_info->_header);
01033 #endif
01034 if (0 == __UNW_LENGTH(unwind_info->_header)) {
01035 __UNW_CONTEXT_ACCESS_IP(scp) =
01036 __UNW_CONTEXT_ACCESS_BR(scp, 0);
01037
01038 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01039 unwind_output("%s zero-size unwind info for ip=0x%llx (segment-relative)",
01040 "unwind_frame() MSG:",
01041 (unsigned long long)ip);
01042 }
01043
01044
01045 return __UNW_OK;
01046 }
01047
01048
01049 slots = ((((__uint64_t)(ip - ptr->_start) & ~0xf) >> 4) * 3) +
01050 ((__uint64_t)(ip - ptr->_start) & 0xf);
01051
01052
01053 if (__UNW_OK != (ret = unwind_process_desc(slots, unwind_info, &state))) {
01054 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01055 unwind_output("unwind_frame() ERROR: %s ip=0x%llx (slots=%llu)",
01056 "can not process",
01057 (unsigned long long)ip,
01058 (unsigned long long)slots);
01059 }
01060 return ret;
01061 }
01062
01063
01064 cfm = __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(__UNW_PFS)) & 0x0000003fffffffff;
01065 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
01066 unwind_output("%s set cfm=0x%llx",
01067 "unwind_frame() INTERNAL MSG:",
01068 (unsigned long long)cfm);
01069 }
01070 bsp = __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(__UNW_BSP));
01071 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
01072 unwind_output("%s pre-set bsp=0x%llx",
01073 "unwind_frame() INTERNAL MSG:",
01074 (unsigned long long)bsp);
01075 }
01076 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(__UNW_BSP)) =
01077 bsp - (__uint64_t)(((cfm & 0x0000000000003f80) >> 7) * sizeof(__uint64_t));
01078 if (_unwind_verbose >= __UNW_VERBOSE_INTERNAL_MSGS) {
01079 unwind_output("%s post-set bsp=0x%llx",
01080 "unwind_frame() INTERNAL MSG:",
01081 (unsigned long long)bsp);
01082 }
01083
01084
01085 if (__UNW_RESTORE_OFF_GR == state._gr[__UNW_SP]._code) {
01086 sp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01087 if (state._gr[__UNW_SP]._reg >= 32) {
01088 #ifdef FOR_GDB
01089 reg_st_loc = (__uint64_t)bsp +
01090 (state._gr[__UNW_SP]._reg - 32) *
01091 sizeof(__uint64_t);
01092 if (!(*__dbg_addr_read)(reg_st_loc,
01093 sizeof(__uint64_t),
01094 (void *)&addr)) {
01095 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01096 unwind_output("unwind_frame() ERROR: %s: %s",
01097 _debugger_string,
01098 "unwind read from target proc failed");
01099 }
01100 return __UNW_INTERNAL_ERROR;
01101 }
01102 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]) =
01103 addr;
01104 #else
01105 reg_stack_loc = (__uint64_t *)((ulong)bsp +
01106 (state._gr[__UNW_SP]._reg - 32) *
01107 sizeof(__uint64_t));
01108 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]) =
01109 *reg_stack_loc;
01110 #endif
01111 } else {
01112 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]) =
01113 __UNW_CONTEXT_ACCESS_GR(scp, state._gr[__UNW_SP]._reg);
01114 }
01115 psp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01116 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01117 unwind_output("%s restored sp=0x%llx (off gr %u)",
01118 "unwind_frame() MSG:",
01119 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]),
01120 state._gr[__UNW_SP]._reg);
01121 }
01122 } else if (__UNW_RESTORE_OFF_BR == state._gr[__UNW_SP]._code) {
01123 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01124 unwind_output("unwind_frame() WARNING: %s",
01125 "sp restoration can not be off a br");
01126 }
01127 ret = __UNW_INV_OP_ERROR;
01128 } else if (__UNW_RESTORE_SP_RELATIVE == state._gr[__UNW_SP]._code) {
01129 sp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01130 #ifdef FOR_GDB
01131 st_loc = (__uint64_t)sp +
01132 state._gr[__UNW_SP]._offset;
01133 if (!(*__dbg_addr_read)(st_loc,
01134 sizeof(__uint64_t),
01135 (void *)&addr)) {
01136 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01137 unwind_output("unwind_frame() ERROR: %s: %s",
01138 _debugger_string,
01139 "unwind read from target proc failed");
01140 }
01141 return __UNW_INTERNAL_ERROR;
01142 }
01143 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]) =
01144 addr;
01145 #else
01146 stack_loc = (__uint64_t *)(ulong)(sp +
01147 state._gr[__UNW_SP]._offset);
01148 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]) =
01149 *stack_loc;
01150 #endif
01151 psp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01152 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01153 unwind_output("%s restored sp=0x%llx (sp offset %llu)",
01154 "unwind_frame() MSG:",
01155 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]),
01156 (unsigned long long)state._gr[__UNW_SP]._offset);
01157 }
01158 } else if (__UNW_RESTORE_PSP_RELATIVE == state._gr[__UNW_SP]._code) {
01159 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01160 unwind_output("unwind_frame() WARNING: %s",
01161 "sp restoration can not be psp-relative");
01162 }
01163 ret = __UNW_INV_OP_ERROR;
01164 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._gr[__UNW_SP]._code) {
01165 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01166 unwind_output("unwind_frame() WARNING: %s and %s",
01167 "sp restoration can not be psp-relative",
01168 "sp has no psp offset provided anyway");
01169 }
01170 ret = __UNW_INV_OP_ERROR;
01171 } else if (__UNW_RESTORE_FIXED_VALUE == state._gr[__UNW_SP]._code) {
01172 sp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01173 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]) +=
01174 (state._frame_size * 16);
01175 psp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01176 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01177 unwind_output("%s restored sp=0x%llx (fixed value of %llu)",
01178 "unwind_frame() MSG:",
01179 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]),
01180 (unsigned long long)state._frame_size);
01181 }
01182 } else {
01183 sp = psp = __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]);
01184 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01185 unwind_output("%s restored sp=0x%llx (unchanged)",
01186 "unwind_frame() MSG:",
01187 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[__UNW_SP]));
01188 }
01189 }
01190
01191
01192 for (i = __UNW_GR_STD_START; i <= __UNW_GR_STD_END; i++) {
01193 if (__UNW_RESTORE_OFF_GR == state._gr[i]._code) {
01194 if (state._gr[i]._reg >= 32) {
01195 #ifdef FOR_GDB
01196 reg_st_loc = (__uint64_t)bsp +
01197 (state._gr[i]._reg - 32) *
01198 sizeof(__uint64_t);
01199 if (!(*__dbg_addr_read)((__uint64_t)reg_st_loc,
01200 sizeof(__uint64_t),
01201 (void *)&addr)) {
01202 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01203 unwind_output("unwind_frame() ERROR: %s: %s",
01204 _debugger_string,
01205 "unwind read from target proc failed");
01206 }
01207 return __UNW_INTERNAL_ERROR;
01208 }
01209 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]) =
01210 addr;
01211 #else
01212 reg_stack_loc = (__uint64_t *)(ulong)((__uint64_t)bsp +
01213 (state._gr[i]._reg - 32) *
01214 sizeof(__uint64_t));
01215 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]) =
01216 *reg_stack_loc;
01217 #endif
01218 } else {
01219 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]) =
01220 __UNW_CONTEXT_ACCESS_GR(scp, state._gr[i]._reg);
01221 }
01222 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01223 unwind_output("%s restored gr[%u]=0x%llx (off gr %u)",
01224 "unwind_frame() MSG:",
01225 _unw_gr_map[i],
01226 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]),
01227 state._gr[i]._reg);
01228 }
01229 } else if (__UNW_RESTORE_OFF_BR == state._gr[i]._code) {
01230 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01231 unwind_output("unwind_frame() WARNING: gr %d %s",
01232 _unw_gr_map[i],
01233 "restoration can not be off a br");
01234 }
01235 ret = __UNW_INV_OP_ERROR;
01236 } else if (__UNW_RESTORE_SP_RELATIVE == state._gr[i]._code) {
01237 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01238 unwind_output("unwind_frame() WARNING: gr %d %s",
01239 _unw_gr_map[i],
01240 "restoration can not be sp-relative");
01241 }
01242 ret = __UNW_INV_OP_ERROR;
01243 } else if (__UNW_RESTORE_PSP_RELATIVE == state._gr[i]._code) {
01244 #ifdef FOR_GDB
01245 st_loc = (__uint64_t)psp -
01246 state._gr[i]._offset;
01247 if (!(*__dbg_addr_read)((__uint64_t)st_loc,
01248 sizeof(__uint64_t),
01249 (void *)&addr)) {
01250 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01251 unwind_output("unwind_frame() ERROR: %s: %s",
01252 _debugger_string,
01253 "unwind read from target proc failed");
01254 }
01255 return __UNW_INTERNAL_ERROR;
01256 }
01257 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]) =
01258 addr;
01259 #else
01260 stack_loc = (__uint64_t *)(ulong)((__uint64_t)psp -
01261 state._gr[i]._offset);
01262 __UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]) =
01263 *stack_loc;
01264 #endif
01265 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01266 unwind_output("%s restored gr[%u]=0x%llx (psp offset %llu)",
01267 "unwind_frame() MSG:",
01268 _unw_gr_map[i],
01269 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]),
01270 (unsigned long long)state._gr[i]._offset);
01271 }
01272 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._gr[i]._code) {
01273 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01274 unwind_output("unwind_frame() WARNING: gr %d %s",
01275 _unw_gr_map[i],
01276 "has no psp offset provided");
01277 }
01278 ret = __UNW_INV_OP_ERROR;
01279 } else if (__UNW_RESTORE_FIXED_VALUE == state._gr[i]._code) {
01280 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01281 unwind_output("unwind_frame() WARNING: gr %d %s",
01282 _unw_gr_map[i],
01283 "restoration can not be a fixed value");
01284 }
01285 ret = __UNW_INV_OP_ERROR;
01286 } else {
01287 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01288 unwind_output("%s restored gr[%u]=0x%llx (unchanged)",
01289 "unwind_frame() MSG:",
01290 _unw_gr_map[i],
01291 (unsigned long long)__UNW_CONTEXT_ACCESS_GR(scp, _unw_gr_map[i]));
01292 }
01293 }
01294 }
01295
01296
01297 for (i = 0; i < __UNW_MAX_FR_PRESERVED; i++) {
01298 if (__UNW_RESTORE_OFF_GR == state._fr[i]._code) {
01299 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01300 unwind_output("unwind_frame() WARNING: fr %d %s",
01301 _unw_fr_map[i],
01302 "restoration can not be off a gr");
01303 }
01304 ret = __UNW_INV_OP_ERROR;
01305 } else if (__UNW_RESTORE_OFF_BR == state._fr[i]._code) {
01306 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01307 unwind_output("unwind_frame() WARNING: fr %d %s",
01308 _unw_fr_map[i],
01309 "restoration can not be off a br");
01310 }
01311 ret = __UNW_INV_OP_ERROR;
01312 } else if (__UNW_RESTORE_SP_RELATIVE == state._fr[i]._code) {
01313 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01314 unwind_output("unwind_frame() WARNING: fr %d %s",
01315 _unw_fr_map[i],
01316 "restoration can not be sp-relative");
01317 }
01318 ret = __UNW_INV_OP_ERROR;
01319 } else if (__UNW_RESTORE_PSP_RELATIVE == state._fr[i]._code) {
01320 #ifdef FOR_GDB
01321 st_loc_fr = (__uint64_t)psp -state._fr[i]._offset;
01322 if (!(*__dbg_addr_read)((__uint64_t)st_loc_fr,
01323 sizeof(__UNW_STRUCT_FPREG),
01324 (void *)&fp_reg)) {
01325 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01326 unwind_output("unwind_frame() ERROR: %s: %s",
01327 _debugger_string,
01328 "unwind read from target proc failed");
01329 }
01330 return __UNW_INTERNAL_ERROR;
01331 }
01332 __UNW_CONTEXT_ACCESS_FR(scp, _unw_fr_map[i]) =
01333 fp_reg;
01334 #else
01335 st_loc_fr = (__UNW_STRUCT_FPREG*)(ulong)((__uint64_t)psp -state._fr[i]._offset);
01336 __UNW_CONTEXT_ACCESS_FR(scp, _unw_fr_map[i]) =
01337 *st_loc_fr;
01338 #endif
01339 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01340 unwind_output("%s restored fr[%u]=%lf (psp offset %llu)",
01341 "unwind_frame() MSG:",
01342 _unw_fr_map[i],
01343 *((long double*) &__UNW_CONTEXT_ACCESS_FR(scp, _unw_fr_map[i])),
01344 (unsigned long long)state._fr[i]._offset);
01345 }
01346 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._fr[i]._code) {
01347 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01348 unwind_output("unwind_frame() WARNING: fr %d %s",
01349 _unw_fr_map[i],
01350 "has no psp offset provided");
01351 }
01352 ret = __UNW_INV_OP_ERROR;
01353 } else if (__UNW_RESTORE_FIXED_VALUE == state._fr[i]._code) {
01354 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01355 unwind_output("unwind_frame() WARNING: fr %d %s",
01356 _unw_fr_map[i],
01357 "restoration can not be a fixed value");
01358 }
01359 ret = __UNW_INV_OP_ERROR;
01360 } else {
01361 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01362 unwind_output("%s restored fr[%u]=0x%llx (unchanged)",
01363 "unwind_frame() MSG:",
01364 _unw_fr_map[i],
01365 *((unsigned long long*) &__UNW_CONTEXT_ACCESS_FR(scp, _unw_fr_map[i])));
01366 }
01367 }
01368 }
01369
01370
01371 for (i = __UNW_BR_STD_START; i <= __UNW_BR_STD_END; i++) {
01372 if (__UNW_RESTORE_OFF_GR == state._br[i]._code) {
01373 if (state._br[i]._reg >= 32) {
01374 #ifdef FOR_GDB
01375 reg_st_loc = (__uint64_t)bsp +
01376 (state._br[i]._reg - 32) *
01377 sizeof(__uint64_t);
01378 if (!(*__dbg_addr_read)((__uint64_t)reg_st_loc,
01379 sizeof(__uint64_t),
01380 (void *)&addr)) {
01381 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01382 unwind_output("unwind_frame() ERROR: %s: %s",
01383 _debugger_string,
01384 "unwind read from target proc failed");
01385 }
01386 return __UNW_INTERNAL_ERROR;
01387 }
01388 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]) =
01389 addr;
01390 #else
01391 reg_stack_loc = (__uint64_t *)(ulong)((__uint64_t)bsp +
01392 (state._br[i]._reg - 32) *
01393 sizeof(__uint64_t));
01394 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]) =
01395 *reg_stack_loc;
01396 #endif
01397 } else {
01398 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]) =
01399 __UNW_CONTEXT_ACCESS_GR(scp, state._br[i]._reg);
01400 }
01401 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01402 unwind_output("%s restored br[%u]=0x%llx (off gr %u)",
01403 "unwind_frame() MSG:",
01404 _unw_br_map[i],
01405 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]),
01406 state._br[i]._reg);
01407 }
01408 } else if (__UNW_RESTORE_OFF_BR == state._br[i]._code) {
01409 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01410 unwind_output("unwind_frame() WARNING: br %d %s",
01411 _unw_br_map[i],
01412 "restoration can not be off a br");
01413 }
01414 ret = __UNW_INV_OP_ERROR;
01415 } else if (__UNW_RESTORE_SP_RELATIVE == state._br[i]._code) {
01416 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01417 unwind_output("unwind_frame() WARNING: br %d %s",
01418 _unw_br_map[i],
01419 "restoration can not be sp-relative");
01420 }
01421 ret = __UNW_INV_OP_ERROR;
01422 } else if (__UNW_RESTORE_PSP_RELATIVE == state._br[i]._code) {
01423 #ifdef FOR_GDB
01424 st_loc = (__uint64_t)psp - state._br[i]._offset;
01425 if (!(*__dbg_addr_read)((__uint64_t)st_loc,
01426 sizeof(__uint64_t),
01427 (void *)&addr)) {
01428 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01429 unwind_output("unwind_frame() ERROR: %s: %s",
01430 _debugger_string,
01431 "unwind read from target proc failed");
01432 }
01433 return __UNW_INTERNAL_ERROR;
01434 }
01435 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]) = addr;
01436 #else
01437 stack_loc = (__uint64_t *)(ulong)((__uint64_t)psp -
01438 state._br[i]._offset);
01439 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]) = *stack_loc;
01440 #endif
01441 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01442 unwind_output("%s restored br[%u]=0x%llx (psp offset %llu)",
01443 "unwind_frame() MSG:",
01444 _unw_br_map[i],
01445 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]),
01446 (unsigned long long)state._br[i]._offset);
01447 }
01448 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._br[i]._code) {
01449 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01450 unwind_output("unwind_frame() WARNING: br %d %s",
01451 _unw_br_map[i],
01452 "has no psp offset provided");
01453 }
01454 ret = __UNW_INV_OP_ERROR;
01455 } else if (__UNW_RESTORE_FIXED_VALUE == state._br[i]._code) {
01456 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01457 unwind_output("unwind_frame() WARNING: br %d %s",
01458 _unw_br_map[i],
01459 "restoration can not be a fixed value");
01460 }
01461 ret = __UNW_INV_OP_ERROR;
01462 } else {
01463 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01464 unwind_output("%s restored br[%u]=0x%llx (unchanged)",
01465 "unwind_frame() MSG:",
01466 _unw_br_map[i],
01467 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]));
01468 }
01469 }
01470 }
01471
01472
01473 if (__UNW_RESTORE_OFF_GR == state._br[__UNW_RP]._code) {
01474 if (state._br[__UNW_RP]._reg >= 32) {
01475 #ifdef FOR_GDB
01476 reg_st_loc = (__uint64_t)bsp +
01477 (state._br[__UNW_RP]._reg - 32) *
01478 sizeof(__uint64_t);
01479 if (!(*__dbg_addr_read)(reg_st_loc,
01480 sizeof(__uint64_t),
01481 (void *)&addr)) {
01482 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01483 unwind_output("unwind_frame() ERROR: %s: %s",
01484 _debugger_string,
01485 "unwind read from target proc failed");
01486 }
01487 return __UNW_INTERNAL_ERROR;
01488 }
01489 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01490 addr;
01491 #else
01492 reg_stack_loc = (__uint64_t *)(ulong)((__uint64_t)bsp +
01493 (state._br[__UNW_RP]._reg - 32) *
01494 sizeof(__uint64_t));
01495 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01496 *reg_stack_loc;
01497 #endif
01498 } else {
01499 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01500 __UNW_CONTEXT_ACCESS_GR(scp, state._br[__UNW_RP]._reg);
01501 }
01502 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01503 unwind_output("%s restored rp=0x%llx (off gr %u)",
01504 "unwind_frame() MSG:",
01505 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]),
01506 state._br[__UNW_RP]._reg);
01507 }
01508 } else if (__UNW_RESTORE_OFF_BR == state._br[__UNW_RP]._code) {
01509 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01510 __UNW_CONTEXT_ACCESS_BR(scp, state._br[__UNW_RP]._reg);
01511 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01512 unwind_output("%s restored rp=0x%llx (off br %u)",
01513 "unwind_frame() MSG:",
01514 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]),
01515 state._br[__UNW_RP]._reg);
01516 }
01517 } else if (__UNW_RESTORE_SP_RELATIVE == state._br[__UNW_RP]._code) {
01518 #ifdef FOR_GDB
01519 st_loc = sp + state._br[__UNW_RP]._offset;
01520 if (!(*__dbg_addr_read)(st_loc,
01521 sizeof(__uint64_t),
01522 (void *)&addr)) {
01523 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01524 unwind_output("unwind_frame() ERROR: %s: %s",
01525 _debugger_string,
01526 "unwind read from target proc failed");
01527 }
01528 return __UNW_INTERNAL_ERROR;
01529 }
01530 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01531 addr;
01532 #else
01533 stack_loc = (__uint64_t *)(ulong)((__uint64_t)sp +
01534 state._br[__UNW_RP]._offset);
01535 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01536 *stack_loc;
01537 #endif
01538 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01539 unwind_output("%s restored rp=0x%llx (sp offset %llu)",
01540 "unwind_frame() MSG:",
01541 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]),
01542 (unsigned long long)state._br[__UNW_RP]._offset);
01543 }
01544 } else if (__UNW_RESTORE_PSP_RELATIVE == state._br[__UNW_RP]._code) {
01545 #ifdef FOR_GDB
01546 st_loc = (__uint64_t)psp -
01547 state._br[__UNW_RP]._offset;
01548 if (!(*__dbg_addr_read)((__uint64_t)st_loc,
01549 sizeof(__uint64_t),
01550 (void *)&addr)) {
01551 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01552 unwind_output("unwind_frame() ERROR: %s: %s",
01553 _debugger_string,
01554 "unwind read from target proc failed");
01555 }
01556 return __UNW_INTERNAL_ERROR;
01557 }
01558 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]) =
01559 addr;
01560 #else
01561 stack_loc = (__uint64_t *)(ulong)((__uint64_t)psp -
01562 state._br[__UNW_RP]._offset);
01563 __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[i]) =
01564 *stack_loc;
01565 #endif
01566 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01567 unwind_output("%s restored rp=0x%llx (psp offset %llu)",
01568 "unwind_frame() MSG:",
01569 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]),
01570 (unsigned long long)state._br[__UNW_RP]._offset);
01571 }
01572 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._br[__UNW_RP]._code) {
01573 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01574 unwind_output("unwind_frame() WARNING: %s",
01575 "rp has no no psp offset provided");
01576 }
01577 ret = __UNW_INV_OP_ERROR;
01578 } else if (__UNW_RESTORE_FIXED_VALUE == state._br[__UNW_RP]._code) {
01579 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01580 unwind_output("unwind_frame() WARNING: %s",
01581 "rp restoration can not be a fixed value");
01582 }
01583 ret = __UNW_INV_OP_ERROR;
01584 } else {
01585 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01586 unwind_output("%s restored rp=0x%llx (unchanged)",
01587 "unwind_frame() MSG:",
01588 (unsigned long long)__UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]));
01589 }
01590 }
01591
01592
01593 __UNW_CONTEXT_ACCESS_IP(scp) = __UNW_CONTEXT_ACCESS_BR(scp, _unw_br_map[__UNW_RP]);
01594 newip = __UNW_CONTEXT_ACCESS_IP(scp);
01595 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01596 unwind_output("%s restored ip=0x%llx (from rp)",
01597 "unwind_frame() MSG:",
01598 (unsigned long long)__UNW_CONTEXT_ACCESS_IP(scp));
01599 }
01600
01601
01602 #ifdef FOR_GDB
01603 if (!(*__dbg_restore_gp)(newip, &gp)) {
01604 #else
01605 if (__UNW_OK != (ret = unwind_restore_gp(newip, &gp))) {
01606 #endif
01607 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01608 unwind_output("unwind_frame() WARNING: %s",
01609 "can not restore gp");
01610 }
01611 } else {
01612 __UNW_CONTEXT_ACCESS_GP(scp) = gp;
01613 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01614 unwind_output("%s restored gp=0x%llx",
01615 "unwind_frame() MSG:",
01616 (unsigned long long)__UNW_CONTEXT_ACCESS_GP(scp));
01617 }
01618 }
01619
01620
01621 for (i = 0; i < __UNW_MAX_AR_PRESERVED; i++) {
01622 if (__UNW_RESTORE_OFF_GR == state._ar[i]._code) {
01623 if (state._ar[i]._reg >= 32) {
01624 #ifdef FOR_GDB
01625 __uint64_t reg_stack_loc1 = bsp;
01626 __uint64_t reg = state._ar[i]._reg;
01627 __uint64_t off = reg - 32ull;
01628 __uint64_t sz = sizeof(__uint64_t);
01629 reg_stack_loc1 += off * sz;
01630 if (!(*__dbg_addr_read)(reg_stack_loc1,
01631 sizeof(__uint64_t),
01632 (void *)&addr)) {
01633 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01634 unwind_output("unwind_frame() ERROR: %s: %s",
01635 _debugger_string,
01636 "unwind read from target proc failed");
01637 }
01638 return __UNW_INTERNAL_ERROR;
01639 }
01640 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) = addr;
01641 #else
01642 reg_stack_loc = (__uint64_t *)(ulong)((__uint64_t)bsp +
01643 (state._ar[i]._reg - 32) *
01644 sizeof(__uint64_t));
01645 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) =
01646 *reg_stack_loc;
01647 #endif
01648 } else {
01649 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) =
01650 __UNW_CONTEXT_ACCESS_GR(scp, state._ar[i]._reg);
01651 }
01652 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01653 unwind_output("%s restored ar[%u]=0x%llx (off gr %u)",
01654 "unwind_frame() MSG:",
01655 __UNW_AR_MAP(i),
01656 (unsigned long long)__UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)),
01657 state._ar[i]._reg);
01658 }
01659 } else if (__UNW_RESTORE_OFF_BR == state._ar[i]._code) {
01660 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01661 unwind_output("unwind_frame() WARNING: ar %d %s",
01662 __UNW_AR_MAP(i),
01663 "restoration can not be off a br");
01664 }
01665 ret = __UNW_INV_OP_ERROR;
01666 } else if (__UNW_RESTORE_SP_RELATIVE == state._ar[i]._code) {
01667 #ifdef FOR_GDB
01668 st_loc = sp + state._ar[i]._offset;
01669 if (!(*__dbg_addr_read)(st_loc,
01670 sizeof(__uint64_t),
01671 (void *)&addr)) {
01672 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01673 unwind_output("unwind_frame() ERROR: %s: %s",
01674 _debugger_string,
01675 "unwind read from target proc failed");
01676 }
01677 return __UNW_INTERNAL_ERROR;
01678 }
01679 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) =
01680 addr;
01681 #else
01682 stack_loc = (__uint64_t *)(ulong)((__uint64_t)sp +
01683 state._ar[i]._offset);
01684 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) =
01685 *stack_loc;
01686 #endif
01687 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01688 unwind_output("%s restored ar[%u]=0x%llx (sp offset %llu)",
01689 "unwind_frame() MSG:",
01690 __UNW_AR_MAP(i),
01691 (unsigned long long)__UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)),
01692 (unsigned long long)state._ar[i]._offset);
01693 }
01694 } else if (__UNW_RESTORE_PSP_RELATIVE == state._ar[i]._code) {
01695 #ifdef FOR_GDB
01696 __uint64_t st_loc = psp - state._ar[i]._offset;
01697 if (!(*__dbg_addr_read)((__uint64_t)st_loc,
01698 sizeof(__uint64_t),
01699 (void *)&addr)) {
01700 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01701 unwind_output("unwind_frame() ERROR: %s: %s",
01702 _debugger_string,
01703 "unwind read from target proc failed");
01704 }
01705 return __UNW_INTERNAL_ERROR;
01706 }
01707 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) =
01708 addr;
01709 #else
01710 stack_loc = (__uint64_t *)(ulong)((__uint64_t)psp -
01711 state._ar[i]._offset);
01712 __UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)) =
01713 *stack_loc;
01714 #endif
01715
01716 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01717 unwind_output("%s restored ar[%u]=0x%llx (psp offset %llu)",
01718 "unwind_frame() MSG:",
01719 __UNW_AR_MAP(i),
01720 (unsigned long long)__UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)),
01721 (unsigned long long)state._ar[i]._offset);
01722 }
01723 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._ar[i]._code) {
01724 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01725 unwind_output("unwind_frame() WARNING: ar %d %s",
01726 __UNW_AR_MAP(i),
01727 "has no psp offset provided");
01728 }
01729 ret = __UNW_INV_OP_ERROR;
01730 } else if (__UNW_RESTORE_FIXED_VALUE == state._ar[i]._code) {
01731 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01732 unwind_output("unwind_frame() WARNING: ar %d %s",
01733 __UNW_AR_MAP(i),
01734 "restoration can not be a fixed value");
01735 }
01736 ret = __UNW_INV_OP_ERROR;
01737 } else {
01738 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01739 unwind_output("%s restored ar[%u]=0x%llx (unchanged)",
01740 "unwind_frame() MSG:",
01741 __UNW_AR_MAP(i),
01742 (unsigned long long)__UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(i)));
01743 }
01744 }
01745 }
01746
01747
01748 __UNW_CONTEXT_ACCESS_AR_EC(scp) = ((__uint64_t)(__UNW_CONTEXT_ACCESS_AR(scp, __UNW_AR_MAP(__UNW_PFS)) && 0x03f0000000000000ull) >> 52);
01749
01750
01751 if (__UNW_RESTORE_OFF_GR == state._preds._code) {
01752 if (state._preds._reg >= 32) {
01753 #ifdef FOR_GDB
01754 reg_st_loc = (__uint64_t)bsp +
01755 (state._preds._reg - 32) *
01756 sizeof(__uint64_t);
01757 if (!(*__dbg_addr_read)(reg_st_loc,
01758 sizeof(__uint64_t),
01759 (void *)&addr)) {
01760 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01761 unwind_output("unwind_frame() ERROR: %s: %s",
01762 _debugger_string,
01763 "unwind read from target proc failed");
01764 }
01765 return __UNW_INTERNAL_ERROR;
01766 }
01767 preds = addr;
01768 #else
01769 reg_stack_loc = (__uint64_t *)(ulong)((__uint64_t)bsp +
01770 (state._preds._reg - 32) *
01771 sizeof(__uint64_t));
01772 preds = *reg_stack_loc;
01773 #endif
01774 } else {
01775 preds = __UNW_CONTEXT_ACCESS_GR(scp, state._preds._reg);
01776 }
01777 #if 0
01778 for (i = 0; i < 64; i++) {
01779 __UNW_CONTEXT_ACCESS_PREDS(scp, i) = (preds & (0x1 << i)) >> i;
01780 }
01781 #else
01782 __UNW_CONTEXT_ACCESS_PREDS(scp) = preds;
01783 #endif
01784 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01785 unwind_output("%s restored preds=0x%016llx (off gr %d)",
01786 "unwind_frame() MSG:",
01787 (unsigned long long)preds,
01788 state._preds._reg);
01789 }
01790 } else if (__UNW_RESTORE_OFF_BR == state._preds._code) {
01791 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01792 unwind_output("unwind_frame() WARNING: %s",
01793 "preds restoration can not be off a BR");
01794 }
01795 ret = __UNW_INV_OP_ERROR;
01796 } else if (__UNW_RESTORE_SP_RELATIVE == state._preds._code) {
01797 #ifdef FOR_GDB
01798 st_loc = (__uint64_t)sp + state._preds._offset;
01799 if (!(*__dbg_addr_read)((__uint64_t)st_loc,
01800 sizeof(__uint64_t),
01801 (void *)&addr)) {
01802 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01803 unwind_output("unwind_frame() ERROR: %s: %s",
01804 _debugger_string,
01805 "unwind read from target proc failed");
01806 }
01807 return __UNW_INTERNAL_ERROR;
01808 }
01809 preds = addr;
01810 #else
01811 stack_loc = (__uint64_t *)(ulong)((__uint64_t)sp +
01812 state._preds._offset);
01813 preds = *stack_loc;
01814 #endif
01815 #if 0
01816 for (i = 0; i < 64; i++) {
01817 __UNW_CONTEXT_ACCESS_PREDS(scp, i) = (preds & (0x1 << i)) >> i;
01818 }
01819 #else
01820 __UNW_CONTEXT_ACCESS_PREDS(scp) = preds;
01821 #endif
01822 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01823 unwind_output("%s restored preds=0x%llx (sp offset %llu)",
01824 "unwind_frame() MSG:",
01825 (unsigned long long)preds,
01826 (unsigned long long)state._preds._offset);
01827 }
01828 } else if (__UNW_RESTORE_PSP_RELATIVE == state._preds._code) {
01829 #ifdef FOR_GDB
01830 st_loc = (__uint64_t)psp - state._preds._offset;
01831 if (!(*__dbg_addr_read)((__uint64_t)st_loc,
01832 sizeof(__uint64_t),
01833 (void *)&addr)) {
01834 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01835 unwind_output("unwind_frame() ERROR: %s: %s",
01836 _debugger_string,
01837 "unwind read from target proc failed");
01838 }
01839 return __UNW_INTERNAL_ERROR;
01840 }
01841 preds = addr;
01842 #else
01843 stack_loc = (__uint64_t *)(ulong)((__uint64_t)psp -
01844 state._preds._offset);
01845 preds = *stack_loc;
01846 #endif
01847 #if 0
01848 for (i = 0; i < 64; i++) {
01849 __UNW_CONTEXT_ACCESS_PREDS(scp, i) = (preds & (0x1 << i)) >> i;
01850 }
01851 #else
01852 __UNW_CONTEXT_ACCESS_PREDS(scp) = preds;
01853 #endif
01854 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01855 unwind_output("%s restored preds=0x%llx (psp offset %llu)",
01856 "unwind_frame() MSG:",
01857 (unsigned long long)preds,
01858 (unsigned long long)state._preds._offset);
01859 }
01860 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._preds._code) {
01861 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01862 unwind_output("unwind_frame() WARNING: %s",
01863 "preds has no psp offset provided");
01864 }
01865 ret = __UNW_INV_OP_ERROR;
01866 } else if (__UNW_RESTORE_FIXED_VALUE == state._preds._code) {
01867 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01868 unwind_output("unwind_frame() WARNING: %s",
01869 "preds restoration can not be a fixed value");
01870 }
01871 ret = __UNW_INV_OP_ERROR;
01872 } else {
01873 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01874 unwind_output("%s restored preds=0x%llx (unchanged)",
01875 "unwind_frame() MSG:",
01876 (unsigned long long)preds);
01877 }
01878 }
01879
01880
01881
01882
01883
01884
01885 if (__UNW_RESTORE_OFF_GR == state._priunat._code) {
01886 if (state._priunat._reg >= 32) {
01887 #ifdef FOR_GDB
01888 reg_st_loc = (__uint64_t)bsp +
01889 (state._priunat._reg - 32) *
01890 sizeof(__uint64_t);
01891 if (!(*__dbg_addr_read)((__uint64_t)reg_st_loc,
01892 sizeof(__uint64_t),
01893 (void *)&addr)) {
01894 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01895 unwind_output("unwind_frame() ERROR: %s: %s",
01896 _debugger_string,
01897 "unwind read from target proc failed");
01898 }
01899 return __UNW_INTERNAL_ERROR;
01900 }
01901 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) = addr;
01902 #else
01903 reg_stack_loc = (__uint64_t *)((__uint64_t)bsp +
01904 (state._priunat._reg - 32) *
01905 sizeof(__uint64_t));
01906 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) =
01907 *reg_stack_loc;
01908 #endif
01909 } else {
01910 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) =
01911 __UNW_CONTEXT_ACCESS_GR(scp, state._priunat._reg);
01912 }
01913 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01914 unwind_output("%s restored priunat=0x%llx (off gr %d)",
01915 "unwind_frame() MSG:",
01916 (unsigned long long)__UNW_CONTEXT_ACCESS_PRIUNAT(scp),
01917 state._priunat._reg);
01918 }
01919 } else if (__UNW_RESTORE_OFF_BR == state._priunat._code) {
01920 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01921 unwind_output("unwind_frame() WARNING: %s",
01922 "priunat restoration can not be off a BR");
01923 }
01924 ret = __UNW_INV_OP_ERROR;
01925 } else if (__UNW_RESTORE_SP_RELATIVE == state._priunat._code) {
01926 #ifdef FOR_GDB
01927 st_loc = (__uint64_t)sp + state._priunat._offset;
01928 if (!(*__dbg_addr_read)(st_loc,
01929 sizeof(__uint64_t),
01930 (void *)&addr)) {
01931 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01932 unwind_output("unwind_frame() ERROR: %s: %s",
01933 _debugger_string,
01934 "unwind read from target proc failed");
01935 }
01936 return __UNW_INTERNAL_ERROR;
01937 }
01938 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) = addr;
01939 #else
01940 stack_loc = (__uint64_t *)((__uint64_t)sp +
01941 state._priunat._offset);
01942 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) = *stack_loc;
01943 #endif
01944 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01945 unwind_output("%s restored priunat=0x%llx (sp offset %llu)",
01946 "unwind_frame() MSG:",
01947 (unsigned long long)__UNW_CONTEXT_ACCESS_PRIUNAT(scp),
01948 (unsigned long long)state._priunat._offset);
01949 }
01950 } else if (__UNW_RESTORE_PSP_RELATIVE == state._priunat._code) {
01951 #ifdef FOR_GDB
01952 st_loc = (__uint64_t)psp -
01953 state._priunat._offset;
01954 if (!(*__dbg_addr_read)(st_loc,
01955 sizeof(__uint64_t),
01956 (void *)&addr)) {
01957 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
01958 unwind_output("unwind_frame() ERROR: %s: %s",
01959 _debugger_string,
01960 "unwind read from target proc failed");
01961 }
01962 return __UNW_INTERNAL_ERROR;
01963 }
01964 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) = addr;
01965 #else
01966 stack_loc = (__uint64_t *)((__uint64_t)psp -
01967 state._priunat._offset);
01968 __UNW_CONTEXT_ACCESS_PRIUNAT(scp) = *stack_loc;
01969 #endif
01970 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01971 unwind_output("%s restored priunat=0x%llx (psp offset %llu)",
01972 "unwind_frame() MSG:",
01973 (unsigned long long)__UNW_CONTEXT_ACCESS_PRIUNAT(scp),
01974 (unsigned long long)state._priunat._offset);
01975 }
01976 } else if (__UNW_TO_RESTORE_PSP_RELATIVE == state._priunat._code) {
01977 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01978 unwind_output("unwind_frame() WARNING: %s",
01979 "priunat has no psp offset provided");
01980 }
01981 ret = __UNW_INV_OP_ERROR;
01982 } else if (__UNW_RESTORE_FIXED_VALUE == state._priunat._code) {
01983 if (_unwind_verbose >= __UNW_VERBOSE_WARNINGS) {
01984 unwind_output("unwind_frame() WARNING: %s",
01985 "priunat restoration can not be a fixed value");
01986 }
01987 ret = __UNW_INV_OP_ERROR;
01988 } else {
01989 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01990 unwind_output("%s restored priunat=0x%llx (unchanged)",
01991 "unwind_frame() MSG:",
01992 (unsigned long long)__UNW_CONTEXT_ACCESS_PRIUNAT(scp));
01993 }
01994 }
01995
01996 if (_unwind_verbose >= __UNW_VERBOSE_MSGS) {
01997 unwind_output("unwind_frame done, returning %d\n", ret );
01998 }
01999
02000 return ret;
02001 }
02002
02003
02004
02005
02006
02007
02008 static void
02009 _Unwind_Find_Entry(struct _Unwind_Context* scp)
02010 {
02011 __unw_error_t ret = __UNW_OK;
02012 __unw_addr_t ip = (__unw_addr_t)__UNW_CONTEXT_ACCESS_IP(scp);
02013 __uint64_t unwind_table_addr, unwind_table_size;
02014 __uint64_t gp = 0L, text_segment_addr = 0L;
02015 __unw_table_entry_t *unwind_table, *ptr, key;
02016 __unw_info_t *unwind_info;
02017
02018 if (__UNW_OK != (ret = unwind_get_unwind_table_data((__uint64_t)ip,
02019 &unwind_table_addr,
02020 &unwind_table_size,
02021 &text_segment_addr)))
02022 {
02023 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS)
02024 {
02025 unwind_output("unwind_frame() ERROR: %s ip=0x%llx",
02026 "can not find unwind table for runtime",
02027 (unsigned long long)ip);
02028 }
02029 return;
02030 }
02031 unwind_table = (__unw_table_entry_t *)unwind_table_addr;
02032
02033
02034 ip -= (__unw_addr_t)text_segment_addr;
02035
02036
02037 key._start = key._end = ip;
02038 unwind_output("unwind_table_entry_compare: Coucou");
02039 ptr = (__unw_table_entry_t *)bsearch((const void *)&key,
02040 (const void *)unwind_table,
02041 (size_t)(unwind_table_size/sizeof(__unw_table_entry_t)),
02042 (size_t)sizeof(__unw_table_entry_t),
02043 unwind_table_entry_compare);
02044 unwind_output("unwind_table_entry_compare: Coucou");
02045
02046 if (ptr == NULL) {
02047 scp->unwind_table_addr = 0ull;
02048 scp->unwind_info_addr = 0ull;
02049 }
02050
02051 }
02052
02053
02054
02055
02056
02057
02058
02059
02060 static const char* _Unwind_Reason_Strings[_URC_INSTALL_CONTEXT+1] =
02061 {
02062 "_URC_NO_REASON",
02063 "_URC_FOREIGN_EXCEPTION_CAUGHT",
02064 "_URC_FATAL_PHASE2_ERROR",
02065 "_URC_FATAL_PHASE1_ERROR",
02066 "_URC_NORMAL_STOP",
02067 "_URC_END_OF_STACK",
02068 "_URC_HANDLER_FOUND",
02069 "_URC_INSTALL_CONTEXT"
02070 };
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088 _Unwind_Reason_Code
02089 _Unwind_RaiseException(
02090 struct _Unwind_Exception *exception_object)
02091 {
02092 struct _Unwind_Context *context;
02093
02094
02095 {
02096 return _URC_END_OF_STACK;
02097 }
02098
02099
02100
02101 {
02102 _Unwind_Exception_Cleanup_Fn destructor
02103 = exception_object->exception_cleanup;
02104
02105 (*destructor)(_URC_FATAL_PHASE2_ERROR, exception_object);
02106 abort();
02107 }
02108
02109 }
02110
02111
02112
02113
02114
02115
02116
02117 _Unwind_Reason_Code
02118 _Unwind_ForceUnwind(
02119 struct _Unwind_Exception *exception_object,
02120 _Unwind_Stop_Fn stop,
02121 void* stop_parameter)
02122 {
02123 _Unwind_Reason_Code reason;
02124 _Unwind_Exception_Cleanup_Fn destructor
02125 = exception_object->exception_cleanup;
02126
02127 struct _Unwind_Context context;
02128
02129
02130
02131 while ((reason = (*stop)(VERSION_NUMBER,
02132 _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
02133 exception_object->exception_class,
02134 exception_object, &context, stop_parameter))
02135 == _URC_NO_REASON)
02136 {
02137 call_personality();
02138 __unwind_frame(context);
02139 }
02140
02141 #ifdef DEBUG
02142 fprintf(stderr, "_Unwind_ForceUnwind; stop function failed because ");
02143 if (reason < 0 || reason > _URC_INSTALL_CONTEXT) {
02144 fprintf(stderr, " reason=%d (0x%x) is garbage\n", reason, reason);
02145 } else {
02146 fprintf(stderr, " %s\n", _Unwind_Reason_Strings[reason]);
02147 }
02148 #endif
02149
02150 (*destructor)(_URC_FATAL_PHASE2_ERROR, exception_object);
02151 abort();
02152 }
02153
02154 void
02155 _Unwind_Resume(
02156 struct _Unwind_Exception *exception_object)
02157 {
02158 }
02159
02160
02161
02162
02163
02164
02165
02166
02167 void
02168 _Unwind_DeleteException(
02169 struct _Unwind_Exception *exception_object)
02170 {
02171 _Unwind_Exception_Cleanup_Fn destructor
02172 = exception_object->exception_cleanup;
02173
02174 (*destructor)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object);
02175 }
02176
02177 uint64_t
02178 _Unwind_GetGR(
02179 struct _Unwind_Context *context,
02180 int index)
02181 {
02182 assert((0 <= index) && (index < 128));
02183 return __UNW_CONTEXT_ACCESS_GR(context, index);
02184 }
02185
02186 void
02187 _Unwind_SetGR(
02188 struct _Unwind_Context *context,
02189 int index,
02190 uint64_t new_value)
02191 {
02192 assert((0 <= index) && (index < 128));
02193 __UNW_CONTEXT_ACCESS_GR(context, index) = new_value;
02194
02195
02196 if (index < 63)
02197 {
02198 __UNW_CONTEXT_ACCESS_AR(context, _unw_ar_map[__UNW_RNAT])
02199 &= ~(0x1 << index);
02200 }
02201 else
02202 {
02203 __UNW_CONTEXT_ACCESS_AR(context, _unw_ar_map[__UNW_UNAT])
02204 &= ~(0x1 << index);
02205 }
02206 }
02207
02208 uint64_t
02209 _Unwind_GetIP(
02210 struct _Unwind_Context *context)
02211 {
02212 return __UNW_CONTEXT_ACCESS_IP(context);
02213 }
02214
02215 void
02216 _Unwind_SetIP(
02217 struct _Unwind_Context *context,
02218 uint64_t new_value)
02219 {
02220 __UNW_CONTEXT_ACCESS_IP(context) = new_value;
02221 }
02222
02223 uint64_t
02224 _Unwind_GetLanguageSpecificData(
02225 struct _Unwind_Context *context)
02226 {
02227 uint64_t* addr = (uint64_t *) context->unwind_info_addr;
02228
02229 return ((uint64_t) addr) + __UNW_LENGTH(*addr);
02230 }
02231
02232
02233 uint64_t
02234 _Unwind_GetRegionStart(
02235 struct _Unwind_Context *context)
02236 {
02237 __unw_table_entry_t* te = (__unw_table_entry_t *) context->unwind_table_addr;
02238 return te->_start;
02239 }