Print this page
6068 libdisasm: previnstr arch op should have a sane default
Reviewed by: Robert Mustacchi <rm@joyent.com>


 155                 dtrace_disx86_str(&dhx->dhx_dis, dhx->dhx_mode, addr, buf,
 156                     buflen);
 157 
 158         return (0);
 159 }
 160 
 161 /* ARGSUSED */
 162 static int
 163 dis_i386_max_instrlen(dis_handle_t *dhp)
 164 {
 165         return (15);
 166 }
 167 
 168 /* ARGSUSED */
 169 static int
 170 dis_i386_min_instrlen(dis_handle_t *dhp)
 171 {
 172         return (1);
 173 }
 174 
 175 /*
 176  * Return the previous instruction.  On x86, we have no choice except to
 177  * disassemble everything from the start of the symbol, and stop when we have
 178  * reached our instruction address.  If we're not in the middle of a known
 179  * symbol, then we return the same address to indicate failure.
 180  */
 181 static uint64_t
 182 dis_i386_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
 183 {
 184         uint64_t *hist, addr, start;
 185         int cur, nseen;
 186         uint64_t res = pc;
 187 
 188         if (n <= 0)
 189                 return (pc);
 190 
 191         if (dhp->dh_lookup(dhp->dh_data, pc, NULL, 0, &start, NULL) != 0 ||
 192             start == pc)
 193                 return (res);
 194 
 195         hist = dis_zalloc(sizeof (uint64_t) * n);
 196 
 197         for (cur = 0, nseen = 0, addr = start; addr < pc; addr = dhp->dh_addr) {
 198                 hist[cur] = addr;
 199                 cur = (cur + 1) % n;
 200                 nseen++;
 201 
 202                 /* if we cannot make forward progress, give up */
 203                 if (dis_disassemble(dhp, addr, NULL, 0) != 0)
 204                         goto done;
 205         }
 206 
 207         if (addr != pc) {
 208                 /*
 209                  * We scanned past %pc, but didn't find an instruction that
 210                  * started at %pc.  This means that either the caller specified
 211                  * an invalid address, or we ran into something other than code
 212                  * during our scan.  Virtually any combination of bytes can be
 213                  * construed as a valid Intel instruction, so any non-code bytes
 214                  * we encounter will have thrown off the scan.
 215                  */
 216                 goto done;
 217         }
 218 
 219         res = hist[(cur + n - MIN(n, nseen)) % n];
 220 
 221 done:
 222         dis_free(hist, sizeof (uint64_t) * n);
 223         return (res);
 224 }
 225 
 226 static int
 227 dis_i386_supports_flags(int flags)
 228 {
 229         int archflags = flags & DIS_ARCH_MASK;
 230 
 231         if (archflags == DIS_X86_SIZE16 || archflags == DIS_X86_SIZE32 ||
 232             archflags == DIS_X86_SIZE64)
 233                 return (1);
 234 
 235         return (0);
 236 }
 237 
 238 static int
 239 dis_i386_instrlen(dis_handle_t *dhp, uint64_t pc)
 240 {
 241         if (dis_disassemble(dhp, pc, NULL, 0) != 0)
 242                 return (-1);
 243 
 244         return (dhp->dh_addr - pc);
 245 }
 246 
 247 dis_arch_t dis_arch_i386 = {
 248         .da_supports_flags      = dis_i386_supports_flags,
 249         .da_handle_attach       = dis_i386_handle_attach,
 250         .da_handle_detach       = dis_i386_handle_detach,
 251         .da_disassemble         = dis_i386_disassemble,
 252         .da_previnstr           = dis_i386_previnstr,
 253         .da_min_instrlen        = dis_i386_min_instrlen,
 254         .da_max_instrlen        = dis_i386_max_instrlen,
 255         .da_instrlen            = dis_i386_instrlen,
 256 };


 155                 dtrace_disx86_str(&dhx->dhx_dis, dhx->dhx_mode, addr, buf,
 156                     buflen);
 157 
 158         return (0);
 159 }
 160 
 161 /* ARGSUSED */
 162 static int
 163 dis_i386_max_instrlen(dis_handle_t *dhp)
 164 {
 165         return (15);
 166 }
 167 
 168 /* ARGSUSED */
 169 static int
 170 dis_i386_min_instrlen(dis_handle_t *dhp)
 171 {
 172         return (1);
 173 }
 174 



















































 175 static int
 176 dis_i386_supports_flags(int flags)
 177 {
 178         int archflags = flags & DIS_ARCH_MASK;
 179 
 180         if (archflags == DIS_X86_SIZE16 || archflags == DIS_X86_SIZE32 ||
 181             archflags == DIS_X86_SIZE64)
 182                 return (1);
 183 
 184         return (0);
 185 }
 186 
 187 static int
 188 dis_i386_instrlen(dis_handle_t *dhp, uint64_t pc)
 189 {
 190         if (dis_disassemble(dhp, pc, NULL, 0) != 0)
 191                 return (-1);
 192 
 193         return (dhp->dh_addr - pc);
 194 }
 195 
 196 dis_arch_t dis_arch_i386 = {
 197         .da_supports_flags      = dis_i386_supports_flags,
 198         .da_handle_attach       = dis_i386_handle_attach,
 199         .da_handle_detach       = dis_i386_handle_detach,
 200         .da_disassemble         = dis_i386_disassemble,

 201         .da_min_instrlen        = dis_i386_min_instrlen,
 202         .da_max_instrlen        = dis_i386_max_instrlen,
 203         .da_instrlen            = dis_i386_instrlen,
 204 };