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 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <errno.h>
00041 #include <strings.h>
00042 #include <sys/unwind.h>
00043 #include "unwind_consumer.h"
00044
00045
00046
00047
00048
00049 static __uint64_t unwind_process_header_desc(__unw_state_info_t **state,
00050 __uint64_t slots, __uint64_t total_slots,
00051 __uint64_t *rlen, char *ptr, __uint64_t size) {
00052 __unw_error_t ret;
00053 __uint64_t count = 0L, num, val;
00054 __uint32_t reg;
00055 unsigned char loc;
00056
00057 if (__UNW_IS_R1(*ptr)) {
00058 count = 1;
00059 *rlen = (__uint64_t)((*ptr) & 0x1f);
00060 if (__UNW_OK != (ret = unwind_state_stack_push(state))) {
00061 return ret;
00062 }
00063 } else if (__UNW_IS_R2(*ptr)) {
00064 count = 2;
00065 num = __leb128_decode(ptr+count, size, &val);
00066 count += num;
00067 *rlen = val;
00068 if (__UNW_OK != (ret = unwind_state_stack_push(state))) {
00069 return ret;
00070 }
00071
00072
00073 if (slots >= total_slots + *rlen) {
00074 loc = (unsigned char)(*ptr & 0x07);
00075 loc <<= 1;
00076 loc |= ((*(ptr+1) & 0x80) >> 7);
00077 reg = (__uint32_t)(*(ptr+1) & 0x7f);
00078 if (loc & 0x08) {
00079 (*state)->_br[__UNW_RP]._code = __UNW_RESTORE_OFF_GR;
00080 (*state)->_br[__UNW_RP]._reg = reg++;
00081 }
00082 if (loc & 0x04) {
00083 (*state)->_ar[__UNW_PFS]._code = __UNW_RESTORE_OFF_GR;
00084 (*state)->_ar[__UNW_PFS]._reg = reg++;
00085 }
00086 if (loc & 0x02) {
00087 (*state)->_gr[__UNW_SP]._code = __UNW_RESTORE_OFF_GR;
00088 (*state)->_gr[__UNW_SP]._reg = reg++;
00089 }
00090 if (loc & 0x01) {
00091 (*state)->_preds._code = __UNW_RESTORE_OFF_GR;
00092 (*state)->_preds._reg = reg;
00093 }
00094 }
00095 } else if (__UNW_IS_R3(*ptr)) {
00096 count = 1;
00097 num = __leb128_decode(ptr+count, size, &val);
00098 count += num;
00099 *rlen = val;
00100 if (__UNW_OK != (ret = unwind_state_stack_push(state))) {
00101 return ret;
00102 }
00103 } else {
00104 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00105 unwind_output("unwind_process_header_desc() ERROR: %s",
00106 "invalid header descriptor");
00107 }
00108 }
00109 return count;
00110 }
00111
00112
00113
00114
00115
00116 static __uint64_t unwind_process_prologue_desc(__unw_state_info_t **state,
00117 __uint64_t slots, __uint64_t total_slots,
00118 __uint64_t rlen, char *ptr, __uint64_t size) {
00119 __uint64_t count = 0L, spill_order = 0L, ret, val, val1, val2, i, j;
00120 __uint32_t reg;
00121 unsigned char loc;
00122
00123 if (__UNW_IS_P1(*ptr)) {
00124 count = 1;
00125 loc = (unsigned char)(*ptr & 0x1f);
00126 for (i = __UNW_BR_STD_START, j = 0; i <= __UNW_BR_STD_END; i++, j++) {
00127 if (loc & (0x1 << j)) {
00128 if ((*state)->_spill_base) {
00129 (*state)->_br[i]._reg = (__uint32_t)(*state)->_spill_order++;
00130 if (__UNW_NO_RESTORE != (*state)->_br[i]._code) {
00131 (*state)->_br[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00132 }
00133 (*state)->_br[i]._offset = (*state)->_spill_base +
00134 (*state)->_spill_offset;
00135 (*state)->_spill_offset += sizeof(__uint64_t);
00136 } else {
00137 (*state)->_br[i]._reg = (__uint32_t)(*state)->_spill_order++;
00138 if (__UNW_NO_RESTORE != (*state)->_br[i]._code) {
00139 (*state)->_br[i]._code = __UNW_TO_RESTORE_PSP_RELATIVE;
00140 }
00141 (*state)->_br[i]._offset = (*state)->_spill_offset;
00142 (*state)->_spill_offset += sizeof(__uint64_t);
00143 }
00144 }
00145 }
00146 } else if (__UNW_IS_P2(*ptr)) {
00147 count = 2;
00148 loc = (unsigned char)(*ptr & 0x0f);
00149 loc <<= 1;
00150 loc |= ((*(ptr+1) & 0x80) >> 7);
00151 reg = (__uint32_t)(*(ptr+1) & 0x7f);
00152 for (i = __UNW_BR_STD_START, j = 0; i <= __UNW_BR_STD_END; i++, j++) {
00153 if (loc & (0x1 << j)) {
00154 if (__UNW_NO_RESTORE != (*state)->_br[i]._code) {
00155 (*state)->_br[i]._code = __UNW_RESTORE_OFF_GR;
00156 }
00157 (*state)->_br[i]._reg = reg++;
00158 }
00159 }
00160 } else if (__UNW_IS_P3(*ptr)) {
00161 count = 2;
00162 loc = (unsigned char)(*ptr & 0x07);
00163 loc <<= 1;
00164 loc |= ((*(ptr+1) & 0x80) >> 7);
00165 reg = (__uint32_t)(*(ptr+1) & 0x7f);
00166 switch (loc) {
00167 case 0:
00168 if (__UNW_NO_RESTORE != (*state)->_gr[__UNW_SP]._code) {
00169 (*state)->_gr[__UNW_SP]._code = __UNW_RESTORE_OFF_GR;
00170 }
00171 (*state)->_gr[__UNW_SP]._reg = reg;
00172 break;
00173 case 1:
00174 if (__UNW_NO_RESTORE != (*state)->_br[__UNW_RP]._code) {
00175 (*state)->_br[__UNW_RP]._code = __UNW_RESTORE_OFF_GR;
00176 }
00177 (*state)->_br[__UNW_RP]._reg = reg;
00178 break;
00179 case 2:
00180 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_PFS]._code ) {
00181 (*state)->_ar[__UNW_PFS]._code = __UNW_RESTORE_OFF_GR;
00182 }
00183 (*state)->_ar[__UNW_PFS]._reg = reg;
00184 break;
00185 case 3:
00186 if (__UNW_NO_RESTORE != (*state)->_preds._code) {
00187 (*state)->_preds._code = __UNW_RESTORE_OFF_GR;
00188 }
00189 (*state)->_preds._reg = reg;
00190 break;
00191 case 4:
00192 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_UNAT]._code) {
00193 (*state)->_ar[__UNW_UNAT]._code = __UNW_RESTORE_OFF_GR;
00194 }
00195 (*state)->_ar[__UNW_UNAT]._reg = reg;
00196 break;
00197 case 5:
00198 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_LC]._code) {
00199 (*state)->_ar[__UNW_LC]._code = __UNW_RESTORE_OFF_GR;
00200 }
00201 (*state)->_ar[__UNW_LC]._reg = reg;
00202 break;
00203 case 6:
00204 if (__UNW_NO_RESTORE != (*state)->_br[__UNW_RP]._code) {
00205 (*state)->_br[__UNW_RP]._code = __UNW_RESTORE_OFF_BR;
00206 }
00207 (*state)->_br[__UNW_RP]._reg = reg;
00208 break;
00209 case 7:
00210 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_RNAT]._code) {
00211 (*state)->_ar[__UNW_RNAT]._code = __UNW_RESTORE_OFF_GR;
00212 }
00213 (*state)->_ar[__UNW_RNAT]._reg = reg;
00214 break;
00215 case 8:
00216 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_BSP]._code) {
00217 (*state)->_ar[__UNW_BSP]._code = __UNW_RESTORE_OFF_GR;
00218 }
00219 (*state)->_ar[__UNW_BSP]._reg = reg;
00220 break;
00221 case 9:
00222 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_BSPSTORE]._code) {
00223 (*state)->_ar[__UNW_BSPSTORE]._code = __UNW_RESTORE_OFF_GR;
00224 }
00225 (*state)->_ar[__UNW_BSPSTORE]._reg = reg;
00226 break;
00227 case 10:
00228 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_FPSR]._code) {
00229 (*state)->_ar[__UNW_FPSR]._code = __UNW_RESTORE_OFF_GR;
00230 }
00231 (*state)->_ar[__UNW_FPSR]._reg = reg;
00232 break;
00233 case 11:
00234 if (__UNW_NO_RESTORE != (*state)->_priunat._code) {
00235 (*state)->_priunat._code = __UNW_RESTORE_OFF_GR;
00236 }
00237 (*state)->_priunat._reg = reg;
00238 break;
00239 default:
00240 break;
00241 }
00242 } else if (__UNW_IS_P4(*ptr)) {
00243 __uint64_t desc_size = ((rlen * 2) + 7 ) / 8,
00244 byte_no = 0L, shift_no = 0L;
00245
00246 count = 1;
00247 if (1 + desc_size > size) {
00248 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00249 unwind_output("unwind_process_prologue_desc() ERROR: %s",
00250 "P4 processing failed with invalid size");
00251 }
00252 count += desc_size;
00253 } else {
00254 for (i = 0; i < (rlen * 2); i += 2) {
00255 byte_no = (i / 8) + 1;
00256 shift_no = i % 8;
00257
00258 loc = (unsigned char)(*(ptr + byte_no));
00259 loc <<= shift_no;
00260 loc >>= 6;
00261
00262 if (0x01 == loc) {
00263 for (j = __UNW_FR_STD_START; j <= __UNW_FR_STD_END; j++) {
00264 if (((__UNW_TO_RESTORE_PSP_RELATIVE == (*state)->_fr[j]._code) ||
00265 (__UNW_RESTORE_PSP_RELATIVE == (*state)->_fr[j]._code)) &&
00266 (spill_order == (*state)->_fr[j]._reg)) {
00267 if (slots <= i/2) {
00268 (*state)->_fr[j]._code = __UNW_NO_RESTORE;
00269 (*state)->_fr[j]._offset = 0L;
00270 }
00271 (*state)->_fr[j]._reg = 0;
00272 spill_order++;
00273 }
00274 }
00275 } else if (0x02 == loc) {
00276 for (j = __UNW_GR_STD_START; j <= __UNW_GR_STD_END; j++) {
00277 if (((__UNW_TO_RESTORE_PSP_RELATIVE == (*state)->_gr[j]._code) ||
00278 (__UNW_RESTORE_PSP_RELATIVE == (*state)->_gr[j]._code)) &&
00279 (spill_order == (*state)->_gr[j]._reg)) {
00280 if (slots <= i/2) {
00281 (*state)->_gr[j]._code = __UNW_NO_RESTORE;
00282 (*state)->_gr[j]._offset = 0L;
00283 }
00284 (*state)->_gr[j]._reg = 0;
00285 spill_order++;
00286 }
00287 }
00288 } else if (0x03 == loc) {
00289 for (j = __UNW_BR_STD_START; j <= __UNW_BR_STD_END; j++) {
00290 if (((__UNW_TO_RESTORE_PSP_RELATIVE == (*state)->_br[j]._code) ||
00291 (__UNW_RESTORE_PSP_RELATIVE == (*state)->_br[j]._code)) &&
00292 (spill_order == (*state)->_br[j]._reg)) {
00293 if (slots <= i/2) {
00294 (*state)->_br[j]._code = __UNW_NO_RESTORE;
00295 (*state)->_br[j]._offset = 0L;
00296 }
00297 (*state)->_br[j]._reg = 0;
00298 spill_order++;
00299 }
00300 }
00301 }
00302
00303 }
00304 count += desc_size;
00305 }
00306 } else if (__UNW_IS_P5(*ptr)) {
00307 __uint32_t frmask = 0;
00308
00309 count = 4;
00310 loc = (unsigned char)((*(ptr+1) & 0xf0) >> 4);
00311 for (i = __UNW_GR_STD_START, j = 0; i <= __UNW_GR_STD_END; i++, j++) {
00312 if (loc & (0x1 << j)) {
00313 if ((*state)->_spill_base) {
00314 (*state)->_gr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00315 if (__UNW_NO_RESTORE != (*state)->_gr[i]._code ) {
00316 (*state)->_gr[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00317 }
00318 (*state)->_gr[i]._offset = (*state)->_spill_base +
00319 (*state)->_spill_offset;
00320 (*state)->_spill_offset += sizeof(__uint64_t);
00321 } else {
00322 (*state)->_gr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00323 if (__UNW_NO_RESTORE != (*state)->_gr[i]._code) {
00324 (*state)->_gr[i]._code = __UNW_TO_RESTORE_PSP_RELATIVE;
00325 }
00326 (*state)->_gr[i]._offset = (*state)->_spill_offset;
00327 (*state)->_spill_offset += sizeof(__uint64_t);
00328 }
00329 }
00330 }
00331 frmask = (__uint32_t)(*(ptr+1) & 0x0f);
00332 frmask <<= 4;
00333 frmask |= *(ptr+2);
00334 frmask <<= 8;
00335 frmask |= *(ptr+3);
00336 for (i = __UNW_FR_STD_START, j = 0; i <= __UNW_FR_STD_END; i++, j++) {
00337 if (frmask & (0x1 << j)) {
00338 if ((*state)->_spill_base) {
00339 if (__UNW_NO_RESTORE != (*state)->_fr[i]._code) {
00340 (*state)->_fr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00341 (*state)->_fr[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00342 (*state)->_fr[i]._offset = (*state)->_spill_base +
00343 (*state)->_spill_offset;
00344 (*state)->_spill_offset += sizeof(long double);
00345 }
00346 } else {
00347 (*state)->_fr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00348 if (__UNW_NO_RESTORE != (*state)->_fr[i]._code) {
00349 (*state)->_fr[i]._code = __UNW_TO_RESTORE_PSP_RELATIVE;
00350 }
00351 (*state)->_fr[i]._offset = (*state)->_spill_offset;
00352 (*state)->_spill_offset += sizeof(long double);
00353 }
00354 }
00355 }
00356 } else if (__UNW_IS_P6(*ptr)) {
00357 count = 1;
00358 loc = (unsigned char)(*ptr & 0x0f);
00359 if (0x00 == (*ptr & 0x10)) {
00360 for (i = __UNW_FR_LOW_START, j = 0; i <= __UNW_FR_LOW_END; i++, j++) {
00361 if (loc & (0x1 << j)) {
00362 if ((*state)->_spill_base) {
00363 (*state)->_fr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00364 if (__UNW_NO_RESTORE != (*state)->_fr[i]._code) {
00365 (*state)->_fr[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00366 }
00367 (*state)->_fr[i]._offset = (*state)->_spill_base +
00368 (*state)->_spill_offset;
00369 (*state)->_spill_offset += sizeof(long double);
00370 } else {
00371 (*state)->_fr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00372 if (__UNW_NO_RESTORE != (*state)->_fr[i]._code) {
00373 (*state)->_fr[i]._code = __UNW_TO_RESTORE_PSP_RELATIVE;
00374 }
00375 (*state)->_fr[i]._offset = (*state)->_spill_offset;
00376 (*state)->_spill_offset += sizeof(long double);
00377 }
00378 }
00379 }
00380 } else {
00381 for (i = __UNW_GR_STD_START, j = 0; i <= __UNW_GR_STD_END; i++, j++) {
00382 if (loc & (0x1 << j)) {
00383 if ((*state)->_spill_base) {
00384 (*state)->_gr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00385 if (__UNW_NO_RESTORE != (*state)->_gr[i]._code) {
00386 (*state)->_gr[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00387 }
00388 (*state)->_gr[i]._offset = (*state)->_spill_base +
00389 (*state)->_spill_offset;
00390 (*state)->_spill_offset += sizeof(__uint64_t);
00391 } else {
00392 (*state)->_gr[i]._reg = (__uint32_t)(*state)->_spill_order++;
00393 if (__UNW_NO_RESTORE != (*state)->_gr[i]._code) {
00394 (*state)->_gr[i]._code = __UNW_TO_RESTORE_PSP_RELATIVE;
00395 }
00396 (*state)->_gr[i]._offset = (*state)->_spill_offset;
00397 (*state)->_spill_offset += sizeof(__uint64_t);
00398 }
00399 }
00400 }
00401 }
00402 } else if (__UNW_IS_P7(*ptr)) {
00403 count = 1;
00404 ret = __leb128_decode(ptr+count, size, &val);
00405 count += ret;
00406 val1 = val;
00407 if (0x00 == (*ptr & 0x0f)) {
00408
00409
00410 ret = __leb128_decode(ptr+count, size, &val);
00411 count += ret;
00412 val2 = val;
00413 }
00414 switch (*ptr & 0x0f) {
00415 case 0:
00416 if (slots > total_slots + val1) {
00417 (*state)->_gr[__UNW_SP]._code = __UNW_RESTORE_FIXED_VALUE;
00418 (*state)->_frame_size = val2;
00419 } else {
00420 (*state)->_gr[__UNW_SP]._code = __UNW_NO_RESTORE;
00421 }
00422 break;
00423 case 1:
00424 if (slots <= total_slots + val1) {
00425 (*state)->_gr[__UNW_SP]._code = __UNW_NO_RESTORE;
00426 }
00427 break;
00428 case 2:
00429 if ((*state)->_spill_base) {
00430 (*state)->_spill_base = val;
00431 (*state)->_spill_offset = 0L;
00432 } else {
00433 (*state)->_spill_base = val;
00434 for (i = __UNW_GR_STD_START; i <= __UNW_GR_STD_END; i++) {
00435 if (__UNW_TO_RESTORE_PSP_RELATIVE == (*state)->_gr[i]._code) {
00436 (*state)->_gr[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00437 (*state)->_gr[i]._offset += (*state)->_spill_base;
00438 val = (*state)->_gr[i]._offset + sizeof(__uint64_t);
00439 }
00440 }
00441 for (i = __UNW_FR_STD_START; i <= __UNW_FR_STD_END; i++) {
00442 if (__UNW_TO_RESTORE_PSP_RELATIVE == (*state)->_fr[i]._code) {
00443 (*state)->_fr[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00444 (*state)->_fr[i]._offset += (*state)->_spill_base;
00445 val = (*state)->_fr[i]._offset + sizeof(long double);
00446 }
00447 }
00448 for (i = __UNW_BR_STD_START; i <= __UNW_BR_STD_END; i++) {
00449 if (__UNW_TO_RESTORE_PSP_RELATIVE == (*state)->_br[i]._code) {
00450 (*state)->_br[i]._code = __UNW_RESTORE_PSP_RELATIVE;
00451 (*state)->_br[i]._offset += (*state)->_spill_base;
00452 val = (*state)->_br[i]._offset + sizeof(__uint64_t);
00453 }
00454 }
00455 (*state)->_spill_offset = val - (*state)->_spill_base;
00456 }
00457 if ((*state)->_spill_base > (*state)->_frame_size) {
00458 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00459 unwind_output("unwind_process_prologue_desc() ERROR: %s",
00460 "P7 processing failed with stack frame overflow");
00461 }
00462 }
00463 break;
00464 case 3:
00465 if (__UNW_NO_RESTORE != (*state)->_gr[__UNW_SP]._code) {
00466 (*state)->_gr[__UNW_SP]._code = __UNW_RESTORE_SP_RELATIVE;
00467 }
00468 (*state)->_gr[__UNW_SP]._offset = val1;
00469 break;
00470 case 4:
00471 if (slots <= total_slots + val1) {
00472 (*state)->_br[__UNW_RP]._code = __UNW_NO_RESTORE;
00473 }
00474 break;
00475 case 5:
00476 if (__UNW_NO_RESTORE != (*state)->_br[__UNW_RP]._code) {
00477 (*state)->_br[__UNW_RP]._code = __UNW_RESTORE_PSP_RELATIVE;
00478 }
00479 (*state)->_br[__UNW_RP]._offset = val1;
00480 break;
00481 case 6:
00482 if (slots <= total_slots + val1) {
00483 (*state)->_ar[__UNW_PFS]._code = __UNW_NO_RESTORE;
00484 }
00485 break;
00486 case 7:
00487 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_PFS]._code) {
00488 (*state)->_ar[__UNW_PFS]._code = __UNW_RESTORE_PSP_RELATIVE;
00489 }
00490 (*state)->_ar[__UNW_PFS]._offset = val1;
00491 break;
00492 case 8:
00493 if (slots <= total_slots + val1) {
00494 (*state)->_preds._code = __UNW_NO_RESTORE;
00495 }
00496 break;
00497 case 9:
00498 if (__UNW_NO_RESTORE != (*state)->_preds._code) {
00499 (*state)->_preds._code = __UNW_RESTORE_PSP_RELATIVE;
00500 }
00501 (*state)->_preds._offset = val1;
00502 break;
00503 case 10:
00504 if (slots <= total_slots + val1) {
00505 (*state)->_ar[__UNW_LC]._code = __UNW_NO_RESTORE;
00506 }
00507 break;
00508 case 11:
00509 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_LC]._code) {
00510 (*state)->_ar[__UNW_LC]._code = __UNW_RESTORE_PSP_RELATIVE;
00511 }
00512 (*state)->_ar[__UNW_LC]._offset = val1;
00513 break;
00514 case 12:
00515 if (slots <= total_slots + val1) {
00516 (*state)->_ar[__UNW_UNAT]._code = __UNW_NO_RESTORE;
00517 }
00518 break;
00519 case 13:
00520 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_UNAT]._code) {
00521 (*state)->_ar[__UNW_UNAT]._code = __UNW_RESTORE_PSP_RELATIVE;
00522 }
00523 (*state)->_ar[__UNW_UNAT]._offset = val1;
00524 break;
00525 case 14:
00526 if (slots <= total_slots + val1) {
00527 (*state)->_ar[__UNW_FPSR]._code = __UNW_NO_RESTORE;
00528 }
00529 break;
00530 case 15:
00531 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_FPSR]._code) {
00532 (*state)->_ar[__UNW_FPSR]._code = __UNW_RESTORE_PSP_RELATIVE;
00533 }
00534 (*state)->_ar[__UNW_FPSR]._offset = val1;
00535 break;
00536 default:
00537 break;
00538 }
00539 } else if (__UNW_IS_P8(*ptr)) {
00540 count = 2;
00541 ret = __leb128_decode(ptr+count, size, &val);
00542 count += ret;
00543 switch (*(ptr+1)) {
00544 case 0:
00545 break;
00546 case 1:
00547 if (__UNW_NO_RESTORE != (*state)->_br[__UNW_RP]._code) {
00548 (*state)->_br[__UNW_RP]._code = __UNW_RESTORE_SP_RELATIVE;
00549 }
00550 (*state)->_br[__UNW_RP]._offset = val;
00551 break;
00552 case 2:
00553 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_PFS]._code) {
00554 (*state)->_ar[__UNW_PFS]._code = __UNW_RESTORE_SP_RELATIVE;
00555 }
00556 (*state)->_ar[__UNW_PFS]._offset = val;
00557 break;
00558 case 3:
00559 if (__UNW_NO_RESTORE != (*state)->_preds._code) {
00560 (*state)->_preds._code = __UNW_RESTORE_SP_RELATIVE;
00561 }
00562 (*state)->_preds._offset = val;
00563 break;
00564 case 4:
00565 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_LC]._code) {
00566 (*state)->_ar[__UNW_LC]._code = __UNW_RESTORE_SP_RELATIVE;
00567 }
00568 (*state)->_ar[__UNW_LC]._offset = val;
00569 break;
00570 case 5:
00571 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_UNAT]._code) {
00572 (*state)->_ar[__UNW_UNAT]._code = __UNW_RESTORE_SP_RELATIVE;
00573 }
00574 (*state)->_ar[__UNW_UNAT]._offset = val;
00575 break;
00576 case 6:
00577 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_FPSR]._code) {
00578 (*state)->_ar[__UNW_FPSR]._code = __UNW_RESTORE_SP_RELATIVE;
00579 }
00580 (*state)->_ar[__UNW_FPSR]._offset = val;
00581 break;
00582 case 7:
00583 if (slots <= total_slots + val) {
00584 (*state)->_ar[__UNW_BSP]._code = __UNW_NO_RESTORE;
00585 }
00586 break;
00587 case 8:
00588 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_BSP]._code) {
00589 (*state)->_ar[__UNW_BSP]._code = __UNW_RESTORE_PSP_RELATIVE;
00590 }
00591 (*state)->_ar[__UNW_BSP]._offset = val;
00592 break;
00593 case 9:
00594 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_BSP]._code) {
00595 (*state)->_ar[__UNW_BSP]._code = __UNW_RESTORE_SP_RELATIVE;
00596 }
00597 (*state)->_ar[__UNW_BSP]._offset = val;
00598 break;
00599 case 10:
00600 if (slots <= total_slots + val) {
00601 (*state)->_ar[__UNW_BSPSTORE]._code = __UNW_NO_RESTORE;
00602 }
00603 break;
00604 case 11:
00605 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_BSPSTORE]._code) {
00606 (*state)->_ar[__UNW_BSPSTORE]._code = __UNW_RESTORE_PSP_RELATIVE;
00607 }
00608 (*state)->_ar[__UNW_BSPSTORE]._offset = val;
00609 break;
00610 case 12:
00611 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_BSPSTORE]._code) {
00612 (*state)->_ar[__UNW_BSPSTORE]._code = __UNW_RESTORE_SP_RELATIVE;
00613 }
00614 (*state)->_ar[__UNW_BSPSTORE]._offset = val;
00615 break;
00616 case 13:
00617 if (slots <= total_slots + val) {
00618 (*state)->_ar[__UNW_RNAT]._code = __UNW_NO_RESTORE;
00619 }
00620 break;
00621 case 14:
00622 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_RNAT]._code) {
00623 (*state)->_ar[__UNW_RNAT]._code = __UNW_RESTORE_PSP_RELATIVE;
00624 }
00625 (*state)->_ar[__UNW_RNAT]._offset = val;
00626 break;
00627 case 15:
00628 if (__UNW_NO_RESTORE != (*state)->_ar[__UNW_RNAT]._code) {
00629 (*state)->_ar[__UNW_RNAT]._code = __UNW_RESTORE_SP_RELATIVE;
00630 }
00631 (*state)->_ar[__UNW_RNAT]._offset = val;
00632 break;
00633 case 16:
00634 if (slots <= total_slots + val) {
00635 (*state)->_priunat._code = __UNW_NO_RESTORE;
00636 }
00637 break;
00638 case 17:
00639 if (__UNW_NO_RESTORE != (*state)->_priunat._code) {
00640 (*state)->_priunat._code = __UNW_RESTORE_PSP_RELATIVE;
00641 }
00642 (*state)->_priunat._offset = val;
00643 break;
00644 case 18:
00645 if (__UNW_NO_RESTORE != (*state)->_priunat._code) {
00646 (*state)->_priunat._code = __UNW_RESTORE_SP_RELATIVE;
00647 }
00648 (*state)->_priunat._offset = val;
00649 break;
00650 default:
00651 break;
00652 }
00653 } else if (__UNW_IS_P9(*ptr)) {
00654 count = 3;
00655 loc = (unsigned char)(*(ptr+1) & 0x0f);
00656 reg = (__uint32_t)(*(ptr+2) & 0x7f);
00657 for (i = __UNW_GR_STD_START, j = 0; i <= __UNW_GR_STD_END; i++, j++) {
00658 if (loc & (0x1 << j)) {
00659 if (__UNW_NO_RESTORE != (*state)->_gr[i]._code) {
00660 (*state)->_gr[i]._code = __UNW_RESTORE_OFF_GR;
00661 }
00662 (*state)->_gr[i]._reg = reg++;
00663 }
00664 }
00665 } else if (__UNW_IS_P10(*ptr)) {
00666 count = 3;
00667
00668
00669 } else if (__UNW_IS_X1(*ptr)) {
00670 count = 2;
00671 #if 0
00672 fprintf(fp, "\tX1: 0x%02x", (unsigned char)*ptr);
00673 #endif
00674 ret = __leb128_decode(ptr+count, size, &val);
00675 count += ret;
00676 #if 0
00677 fprintf(fp, "time=%llu\n", (unsigned long long) val);
00678 fprintf(fp, "\t\treg = 0x%0x, ",
00679 (unsigned char)*(ptr+1));
00680 #endif
00681 ret = __leb128_decode(ptr+count, size, &val);
00682 count += ret;
00683 #if 0
00684 fprintf(fp, "offset = %lld\n", (long long)val);
00685 #endif
00686 } else if (__UNW_IS_X2(*ptr)) {
00687 count = 3;
00688 #if 0
00689 fprintf(fp, "\tX1: 0x%02x", (unsigned char)*ptr);
00690 #endif
00691 ret = __leb128_decode(ptr+count, size, &val);
00692 count += ret;
00693 #if 0
00694 fprintf(fp, "time=%llu\n",
00695 (unsigned long long) val);
00696 fprintf(fp, "\t\treg = 0x%0x, ",
00697 (unsigned char)*(ptr+1));
00698 fprintf(fp, "treg = 0x%0x\n",
00699 (unsigned char)*(ptr+2));
00700 #endif
00701 } else {
00702 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00703 unwind_output("unwind_process_prologue_desc() ERROR: %s 0x%x",
00704 "invalid prologue descriptor", *ptr & 0xff);
00705 }
00706 }
00707 return count;
00708 }
00709
00710
00711
00712
00713
00714 static __uint64_t unwind_process_body_desc(__unw_state_info_t **state,
00715 __uint64_t slots, __uint64_t total_slots,
00716 __uint64_t rlen, char *ptr, __uint64_t size) {
00717 __unw_error_t ret;
00718 __uint64_t count = 0L, num, val, val1, val2;
00719
00720 if (__UNW_IS_B1(*ptr)) {
00721 count = 1;
00722 val = (__uint64_t)(*ptr & 0x1f);
00723
00724 if (0x00 == (*ptr & 0x20)) {
00725 (*state)->_label = val;
00726 } else {
00727 if (slots < total_slots + rlen) {
00728 if (__UNW_OK != (ret = unwind_state_stack_search(state, val))) {
00729 return ret;
00730 }
00731 }
00732 }
00733 } else if (__UNW_IS_B2(*ptr)) {
00734 count = 1;
00735 num = __leb128_decode(ptr+count, size, &val);
00736 count += num;
00737
00738 if (slots < total_slots + rlen) {
00739 if (slots > total_slots + rlen - val) {
00740 (*state)->_gr[__UNW_SP]._code = __UNW_NO_RESTORE;
00741 }
00742 } else {
00743 if (__UNW_OK != (ret = unwind_state_stack_pop(
00744 (__uint64_t)((*ptr & 0x1f) + 1)))) {
00745 return ret;
00746 }
00747 if (__UNW_OK != (ret = unwind_state_stack_top(state))) {
00748 return ret;
00749 }
00750 }
00751 } else if (__UNW_IS_B3(*ptr)) {
00752 count = 1;
00753 num = __leb128_decode(ptr+count, size, &val);
00754 count += num;
00755 val1 = val;
00756 num = __leb128_decode(ptr+count, size, &val);
00757 count += num;
00758 val2 = val;
00759
00760 if (slots < total_slots + rlen) {
00761 if (slots > total_slots + rlen - val) {
00762 (*state)->_gr[__UNW_SP]._code = __UNW_NO_RESTORE;
00763 }
00764 } else {
00765 if (__UNW_OK != (ret = unwind_state_stack_pop(val2 + 1))) {
00766 return ret;
00767 }
00768 if (__UNW_OK != (ret = unwind_state_stack_top(state))) {
00769 return ret;
00770 }
00771 }
00772 } else if (__UNW_IS_B4(*ptr)) {
00773 count = 1;
00774 num = __leb128_decode(ptr+count, size, &val);
00775 count += num;
00776
00777 if (0x00 == (*ptr & 0x08)) {
00778 (*state)->_label = val;
00779 } else {
00780 if (slots < total_slots + rlen) {
00781 if (__UNW_OK != (ret = unwind_state_stack_search(state, val))) {
00782 return ret;
00783 }
00784 }
00785 }
00786 } else {
00787 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00788 unwind_output("unwind_process_body_desc() ERROR: %s",
00789 "invalid body descriptor");
00790 }
00791 }
00792 return count;
00793 }
00794
00795
00796
00797
00798 __unw_error_t unwind_process_desc(__uint64_t slots, __unw_info_t *info,
00799 __unw_state_info_t *state) {
00800 __unw_state_info_t *state_ptr;
00801 __uint32_t ip_found = 0;
00802 __uint64_t rlen, count = 0L, size = 0L, retnum = 0L, total_slots = 0L;
00803 char *ptr = NULL;
00804 enum { __UNW_UNDEF, __UNW_PROLOGUE, __UNW_BODY } desc_id = __UNW_UNDEF;
00805
00806
00807 size = (__uint64_t)(__UNW_LENGTH((info->_header) *
00808 sizeof(__unw_dbl_word_t)));
00809
00810
00811 if (__UNW_VER(info->_header) != 1) {
00812 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00813 unwind_output("unwind_process_desc() ERROR: %s (%d)",
00814 "invalid version", __UNW_VER(info->_header));
00815 }
00816 return __UNW_INV_VERSION_ERROR;
00817 }
00818
00819
00820 if (__UNW_OK != unwind_state_stack_reset()) {
00821 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00822 unwind_output("unwind_process_desc() ERROR: %s",
00823 "can not reset state stack");
00824 return __UNW_INTERNAL_ERROR;
00825 }
00826 }
00827
00828
00829 ptr = (char *)info->_body;
00830 count = 0L;
00831 while (count < size) {
00832 if (__UNW_IS_HEADER(*ptr)) {
00833
00834 if (ip_found) {
00835 break;
00836 }
00837 if (__UNW_IS_PROLOGUE_HEADER(*ptr)) {
00838 desc_id = __UNW_PROLOGUE;
00839 if (0 == (retnum = unwind_process_header_desc(&state_ptr,
00840 slots, total_slots, &rlen, ptr, size-count))) {
00841 return __UNW_INTERNAL_ERROR;
00842 }
00843 total_slots += rlen;
00844 if (slots < total_slots) {
00845
00846 ip_found = 1;
00847 }
00848 } else if (__UNW_IS_BODY_HEADER(*ptr)) {
00849 desc_id = __UNW_BODY;
00850 if (0 == (retnum = unwind_process_header_desc(&state_ptr,
00851 slots, total_slots, &rlen, ptr, size-count))) {
00852 return __UNW_INTERNAL_ERROR;
00853 }
00854 total_slots += rlen;
00855 if (slots < total_slots) {
00856
00857 ip_found = 1;
00858 }
00859 } else {
00860 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00861 unwind_output("unwind_process_desc() ERROR: %s (0x%x)",
00862 "invalid header",
00863 (unsigned char)*ptr);
00864 }
00865 return __UNW_INTERNAL_ERROR;
00866 }
00867 } else {
00868 if (__UNW_PROLOGUE == desc_id) {
00869 fprintf(stderr, "\t\t\t\tcount = 0x%llx\n", count);
00870 if (0 == (retnum = unwind_process_prologue_desc(&state_ptr,
00871 slots, total_slots - rlen, rlen, ptr, size-count))) {
00872 return __UNW_INTERNAL_ERROR;
00873 }
00874 } else if (__UNW_BODY == desc_id) {
00875 if (0 == (retnum = unwind_process_body_desc(&state_ptr,
00876 slots, total_slots - rlen, rlen, ptr, size-count))) {
00877 return __UNW_INTERNAL_ERROR;
00878 }
00879 } else {
00880 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00881 unwind_output("unwind_process_desc() ERROR: %s",
00882 "invalid prologue/body");
00883 }
00884 return __UNW_INTERNAL_ERROR;
00885 }
00886 }
00887 count += retnum;
00888 ptr += retnum;
00889 }
00890
00891
00892 if (!ip_found) {
00893 if (_unwind_verbose >= __UNW_VERBOSE_ERRORS) {
00894 unwind_output("unwind_process_desc() ERROR: %s",
00895 "ip not found in unwind info");
00896 }
00897 return __UNW_INTERNAL_ERROR;
00898 }
00899
00900
00901 *state = *state_ptr;
00902
00903 return __UNW_OK;
00904 }