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
00046
00047
00048 #include "xlateincl.h"
00049
00050 #ifndef TURN_OFF_MEMO
00051
00052
00053
00054
00055
00056 static int
00057 look_in_memo_data(xlate_table_con tab,
00058 int isNewAddress,
00059 struct memo_s *memodata,
00060 Elf64_Addr addr_in,
00061 Elf64_Addr* addr_out,
00062 xlate_block *range_out)
00063 {
00064 int retstatus;
00065 if(isNewAddress) {
00066 xlate_block *xbp;
00067 if(addr_in < memodata->mm_low_new_addr ||
00068 addr_in >= memodata->mm_high_new_addr) {
00069 return XLATE_TB_STATUS_NO_SUCH_ADDR_IN_TABLE;
00070 }
00071 xbp = &memodata->mm_block;
00072 if(addr_in >= xbp->xe_new_address &&
00073 addr_in < (xbp->xe_new_address + xbp->xe_new_range)) {
00074 *addr_out = _xlate_get_out_from_ranges(addr_in,
00075 xbp->xe_new_address,
00076 xbp->xe_old_address,
00077 xbp->xe_old_range);
00078 if(range_out) {
00079 *range_out = *xbp;
00080 }
00081 return XLATE_TB_STATUS_NO_ERROR;
00082
00083 }
00084
00085
00086
00087 retstatus = tab->xc_get_range_from_block(tab,
00088 isNewAddress,addr_in,
00089 1,
00090 tab->xc_ubh_array+memodata->mm_ublock_index,
00091 addr_out,
00092 range_out);
00093 return retstatus;
00094
00095 }
00096 {
00097 xlate_block *xbp;
00098 if(addr_in < memodata->mm_low_old_addr ||
00099 addr_in >= memodata->mm_high_old_addr) {
00100 return XLATE_TB_STATUS_NO_SUCH_ADDR_IN_TABLE;
00101 }
00102 xbp = &memodata->mm_block;
00103 if(addr_in >= xbp->xe_old_address &&
00104 addr_in < (xbp->xe_old_address + xbp->xe_old_range)) {
00105 *addr_out = _xlate_get_out_from_ranges(addr_in,
00106 xbp->xe_old_address,
00107 xbp->xe_new_address,
00108 xbp->xe_new_range);
00109 if(range_out) {
00110 *range_out = *xbp;
00111 }
00112 return XLATE_TB_STATUS_NO_ERROR;
00113 }
00114
00115
00116
00117 retstatus = tab->xc_get_range_from_block(tab,
00118 isNewAddress,addr_in,
00119 1,
00120 tab->xc_ubh_array+memodata->mm_ublock_index,
00121 addr_out,
00122 range_out);
00123 return retstatus;
00124 }
00125 }
00126 #endif
00127
00128
00129
00130
00131
00132
00133 int _xlate_binary_search_for_addr(xlate_table_con tab,
00134 int isNewAddress,
00135 Elf64_Addr addr_in,
00136 Elf64_Addr* addr_out,
00137 xlate_block *range_out)
00138 {
00139 Uword last_block_index = tab->xc_hdr.ich_num_blocks - 1;
00140 Uword high = last_block_index;
00141 Uword low = 0;
00142 Uword probe = 0;
00143 Uword final;
00144 Elf64_Addr low_lowaddr = 0;
00145 Elf64_Addr lowaddr;
00146 Elf64_Addr high_lowaddr = 0;
00147 Elf64_Addr highaddr;
00148
00149 int retstatus = XLATE_TB_STATUS_NO_ERROR;
00150 struct memo_s *memodata;
00151
00152 #if 0
00153 printf("dadebug binary search: new? %d addr 0x%llx\n",isNewAddress,addr_in);
00154 #endif
00155 #ifndef TURN_OFF_MEMO
00156 if(isNewAddress) {
00157 memodata = &tab->xc_memo_new;
00158 } else {
00159 memodata = &tab->xc_memo_old;
00160 }
00161 if(memodata->mm_is_valid) {
00162 retstatus = look_in_memo_data(tab,isNewAddress,
00163 memodata,
00164 addr_in, addr_out,range_out);
00165 if(retstatus == XLATE_TB_STATUS_NO_ERROR) {
00166
00167 #if 0
00168 printf("dadebug FOUND in memo\n");
00169 #endif
00170 return retstatus;
00171 }
00172 }
00173 #if 0
00174 printf("dadebug invalidate memo, search\n");
00175 #endif
00176 memodata->mm_is_valid = 0;
00177 #endif
00178
00179 retstatus = tab->xc_block_header_indexer(tab,
00180 isNewAddress, low,&low_lowaddr,
00181 &highaddr,tab->xc_ubh_array+low);
00182 if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
00183
00184 return retstatus;
00185 }
00186 if(high == low) {
00187 high_lowaddr = low_lowaddr;
00188 } else {
00189 retstatus = tab->xc_block_header_indexer(tab,
00190 isNewAddress, high,&high_lowaddr,
00191 &highaddr,tab->xc_ubh_array+high);
00192 if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
00193
00194 return retstatus;
00195 }
00196 }
00197
00198 while((high-low)>1) {
00199 probe = (low+high)/2;
00200 retstatus = tab->xc_block_header_indexer(tab,
00201 isNewAddress, probe,&lowaddr,
00202 &highaddr,tab->xc_ubh_array+probe);
00203 if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
00204
00205 return retstatus;
00206 }
00207 if(lowaddr <= addr_in) {
00208 low = probe;
00209 low_lowaddr = lowaddr;
00210 } else {
00211 high = probe;
00212 high_lowaddr = lowaddr;
00213 }
00214 };
00215
00216 if(addr_in < high_lowaddr) {
00217 final = low;
00218 } else {
00219 final = high;
00220 }
00221
00222 retstatus = tab->xc_block_header_indexer(tab,
00223 isNewAddress,
00224 final,&lowaddr,
00225 &highaddr,tab->xc_ubh_array+final);
00226 if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
00227
00228 return retstatus;
00229 }
00230
00231 if(addr_in >= highaddr || addr_in < lowaddr) {
00232 return XLATE_TB_STATUS_NO_SUCH_ADDR_IN_TABLE;
00233 }
00234
00235 retstatus = tab->xc_get_range_from_block(tab,
00236 isNewAddress,addr_in,
00237 0,
00238 tab->xc_ubh_array+final,
00239 addr_out,
00240 range_out);
00241
00242
00243 return retstatus;
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 int _xlate_special_search_for_addr(xlate_table_con tab,
00261 int isNewAddress,
00262 Elf64_Addr addr_in,
00263 Elf64_Addr* addr_out,
00264 xlate_block *range_out)
00265 {
00266 Uword last_block_index = tab->xc_hdr.ich_num_blocks - 1;
00267 Uword curblock;
00268 Elf64_Addr lowaddr;
00269 Elf64_Addr highaddr;
00270 int retstatus = XLATE_TB_STATUS_NO_ERROR;
00271 struct memo_s *memodata;
00272
00273
00274 #if 0
00275 printf("dadebug special search: new? %d addr 0x%llx\n",isNewAddress,addr_in);
00276 #endif
00277 #ifndef TURN_OFF_MEMO
00278 if(isNewAddress) {
00279 memodata = &tab->xc_memo_new;
00280 } else {
00281 memodata = &tab->xc_memo_old;
00282 }
00283 if(memodata->mm_is_valid) {
00284 retstatus = look_in_memo_data(tab,isNewAddress,
00285 memodata,
00286 addr_in, addr_out,range_out);
00287 if(retstatus == XLATE_TB_STATUS_NO_ERROR) {
00288 #if 0
00289 printf("dadebug FOUND in memo\n");
00290 #endif
00291 return retstatus;
00292 }
00293 }
00294
00295 #if 0
00296 printf("dadebug invalidate memo, search\n");
00297 #endif
00298 memodata->mm_is_valid = 0;
00299 #endif
00300 for(curblock = 0; curblock <= last_block_index; ++curblock) {
00301 retstatus = tab->xc_block_header_indexer(tab,
00302 isNewAddress, curblock,&lowaddr,
00303 &highaddr,tab->xc_ubh_array+curblock);
00304 if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
00305
00306 return retstatus;
00307 }
00308 if(addr_in < lowaddr || addr_in >= highaddr) {
00309 continue;
00310 }
00311
00312
00313 retstatus = tab->xc_get_range_from_block(tab,
00314 isNewAddress,addr_in,
00315 0,
00316 tab->xc_ubh_array+curblock,
00317 addr_out,
00318 range_out);
00319 if(retstatus == XLATE_TB_STATUS_NO_SUCH_ADDR_IN_TABLE) {
00320
00321 continue;
00322 }
00323
00324
00325
00326 return retstatus;
00327
00328 }
00329 return XLATE_TB_STATUS_NO_SUCH_ADDR_IN_TABLE;
00330
00331 }
00332
00333