xref: /PHP-8.3/ext/opcache/jit/libudis86/udis86.c (revision 52136123)
1 /* udis86 - libudis86/udis86.c
2  *
3  * Copyright (c) 2002-2013 Vivek Thampi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without modification,
7  * are permitted provided that the following conditions are met:
8  *
9  *     * Redistributions of source code must retain the above copyright notice,
10  *       this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above copyright notice,
12  *       this list of conditions and the following disclaimer in the documentation
13  *       and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "udint.h"
28 #include "extern.h"
29 #include "decode.h"
30 
31 #if !defined(__UD_STANDALONE__)
32 # if HAVE_STRING_H
33 #  include <string.h>
34 # endif
35 #endif /* !__UD_STANDALONE__ */
36 
37 static void ud_inp_init(struct ud *u);
38 
39 /* =============================================================================
40  * ud_init
41  *    Initializes ud_t object.
42  * =============================================================================
43  */
44 extern void
ud_init(struct ud * u)45 ud_init(struct ud* u)
46 {
47   memset((void*)u, 0, sizeof(struct ud));
48   ud_set_mode(u, 16);
49   u->mnemonic = UD_Iinvalid;
50   ud_set_pc(u, 0);
51 #ifndef __UD_STANDALONE__
52   ud_set_input_file(u, stdin);
53 #endif /* __UD_STANDALONE__ */
54 
55   ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
56 }
57 
58 
59 /* =============================================================================
60  * ud_disassemble
61  *    Disassembles one instruction and returns the number of
62  *    bytes disassembled. A zero means end of disassembly.
63  * =============================================================================
64  */
65 extern unsigned int
ud_disassemble(struct ud * u)66 ud_disassemble(struct ud* u)
67 {
68   int len;
69   if (u->inp_end) {
70     return 0;
71   }
72   if ((len = ud_decode(u)) > 0) {
73     if (u->translator != NULL) {
74       u->asm_buf[0] = '\0';
75       u->translator(u);
76     }
77   }
78   return len;
79 }
80 
81 
82 /* =============================================================================
83  * ud_set_mode() - Set Disassemly Mode.
84  * =============================================================================
85  */
86 extern void
ud_set_mode(struct ud * u,uint8_t m)87 ud_set_mode(struct ud* u, uint8_t m)
88 {
89   switch(m) {
90   case 16:
91   case 32:
92   case 64: u->dis_mode = m ; return;
93   default: u->dis_mode = 16; return;
94   }
95 }
96 
97 /* =============================================================================
98  * ud_set_vendor() - Set vendor.
99  * =============================================================================
100  */
101 extern void
ud_set_vendor(struct ud * u,unsigned v)102 ud_set_vendor(struct ud* u, unsigned v)
103 {
104   switch(v) {
105   case UD_VENDOR_INTEL:
106     u->vendor = v;
107     break;
108   case UD_VENDOR_ANY:
109     u->vendor = v;
110     break;
111   default:
112     u->vendor = UD_VENDOR_AMD;
113   }
114 }
115 
116 /* =============================================================================
117  * ud_set_pc() - Sets code origin.
118  * =============================================================================
119  */
120 extern void
ud_set_pc(struct ud * u,uint64_t o)121 ud_set_pc(struct ud* u, uint64_t o)
122 {
123   u->pc = o;
124 }
125 
126 /* =============================================================================
127  * ud_set_syntax() - Sets the output syntax.
128  * =============================================================================
129  */
130 extern void
ud_set_syntax(struct ud * u,void (* t)(struct ud *))131 ud_set_syntax(struct ud* u, void (*t)(struct ud*))
132 {
133   u->translator = t;
134 }
135 
136 /* =============================================================================
137  * ud_insn() - returns the disassembled instruction
138  * =============================================================================
139  */
140 const char*
ud_insn_asm(const struct ud * u)141 ud_insn_asm(const struct ud* u)
142 {
143   return u->asm_buf;
144 }
145 
146 /* =============================================================================
147  * ud_insn_offset() - Returns the offset.
148  * =============================================================================
149  */
150 uint64_t
ud_insn_off(const struct ud * u)151 ud_insn_off(const struct ud* u)
152 {
153   return u->insn_offset;
154 }
155 
156 
157 /* =============================================================================
158  * ud_insn_hex() - Returns hex form of disassembled instruction.
159  * =============================================================================
160  */
161 const char*
ud_insn_hex(struct ud * u)162 ud_insn_hex(struct ud* u)
163 {
164   u->insn_hexcode[0] = 0;
165   if (!u->error) {
166     unsigned int i;
167     const unsigned char *src_ptr = ud_insn_ptr(u);
168     char* src_hex;
169     src_hex = (char*) u->insn_hexcode;
170     /* for each byte used to decode instruction */
171     for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2;
172          ++i, ++src_ptr) {
173       sprintf(src_hex, "%02x", *src_ptr & 0xFF);
174       src_hex += 2;
175     }
176   }
177   return u->insn_hexcode;
178 }
179 
180 
181 /* =============================================================================
182  * ud_insn_ptr
183  *    Returns a pointer to buffer containing the bytes that were
184  *    disassembled.
185  * =============================================================================
186  */
187 extern const uint8_t*
ud_insn_ptr(const struct ud * u)188 ud_insn_ptr(const struct ud* u)
189 {
190   return (u->inp_buf == NULL) ?
191             u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr);
192 }
193 
194 
195 /* =============================================================================
196  * ud_insn_len
197  *    Returns the count of bytes disassembled.
198  * =============================================================================
199  */
200 extern unsigned int
ud_insn_len(const struct ud * u)201 ud_insn_len(const struct ud* u)
202 {
203   return u->inp_ctr;
204 }
205 
206 
207 /* =============================================================================
208  * ud_insn_get_opr
209  *    Return the operand struct representing the nth operand of
210  *    the currently disassembled instruction. Returns NULL if
211  *    there's no such operand.
212  * =============================================================================
213  */
214 const struct ud_operand*
ud_insn_opr(const struct ud * u,unsigned int n)215 ud_insn_opr(const struct ud *u, unsigned int n)
216 {
217   if (n > 3 || u->operand[n].type == UD_NONE) {
218     return NULL;
219   } else {
220     return &u->operand[n];
221   }
222 }
223 
224 
225 /* =============================================================================
226  * ud_opr_is_sreg
227  *    Returns non-zero if the given operand is of a segment register type.
228  * =============================================================================
229  */
230 int
ud_opr_is_sreg(const struct ud_operand * opr)231 ud_opr_is_sreg(const struct ud_operand *opr)
232 {
233   return opr->type == UD_OP_REG &&
234          opr->base >= UD_R_ES   &&
235          opr->base <= UD_R_GS;
236 }
237 
238 
239 /* =============================================================================
240  * ud_opr_is_sreg
241  *    Returns non-zero if the given operand is of a general purpose
242  *    register type.
243  * =============================================================================
244  */
245 int
ud_opr_is_gpr(const struct ud_operand * opr)246 ud_opr_is_gpr(const struct ud_operand *opr)
247 {
248   return opr->type == UD_OP_REG &&
249          opr->base >= UD_R_AL   &&
250          opr->base <= UD_R_R15;
251 }
252 
253 
254 /* =============================================================================
255  * ud_set_user_opaque_data
256  * ud_get_user_opaque_data
257  *    Get/set user opaqute data pointer
258  * =============================================================================
259  */
260 void
ud_set_user_opaque_data(struct ud * u,void * opaque)261 ud_set_user_opaque_data(struct ud * u, void* opaque)
262 {
263   u->user_opaque_data = opaque;
264 }
265 
266 void*
ud_get_user_opaque_data(const struct ud * u)267 ud_get_user_opaque_data(const struct ud *u)
268 {
269   return u->user_opaque_data;
270 }
271 
272 
273 /* =============================================================================
274  * ud_set_asm_buffer
275  *    Allow the user to set an assembler output buffer. If `buf` is NULL,
276  *    we switch back to the internal buffer.
277  * =============================================================================
278  */
279 void
ud_set_asm_buffer(struct ud * u,char * buf,size_t size)280 ud_set_asm_buffer(struct ud *u, char *buf, size_t size)
281 {
282   if (buf == NULL) {
283     ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
284   } else {
285     u->asm_buf = buf;
286     u->asm_buf_size = size;
287   }
288 }
289 
290 
291 /* =============================================================================
292  * ud_set_sym_resolver
293  *    Set symbol resolver for relative targets used in the translation
294  *    phase.
295  *
296  *    The resolver is a function that takes a uint64_t address and returns a
297  *    symbolic name for the that address. The function also takes a second
298  *    argument pointing to an integer that the client can optionally set to a
299  *    non-zero value for offsetted targets. (symbol+offset) The function may
300  *    also return NULL, in which case the translator only prints the target
301  *    address.
302  *
303  *    The function pointer maybe NULL which resets symbol resolution.
304  * =============================================================================
305  */
306 void
ud_set_sym_resolver(struct ud * u,const char * (* resolver)(struct ud *,uint64_t addr,int64_t * offset))307 ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*,
308                                                           uint64_t addr,
309                                                           int64_t *offset))
310 {
311   u->sym_resolver = resolver;
312 }
313 
314 
315 /* =============================================================================
316  * ud_insn_mnemonic
317  *    Return the current instruction mnemonic.
318  * =============================================================================
319  */
320 enum ud_mnemonic_code
ud_insn_mnemonic(const struct ud * u)321 ud_insn_mnemonic(const struct ud *u)
322 {
323   return u->mnemonic;
324 }
325 
326 
327 /* =============================================================================
328  * ud_lookup_mnemonic
329  *    Looks up mnemonic code in the mnemonic string table.
330  *    Returns NULL if the mnemonic code is invalid.
331  * =============================================================================
332  */
333 const char*
ud_lookup_mnemonic(enum ud_mnemonic_code c)334 ud_lookup_mnemonic(enum ud_mnemonic_code c)
335 {
336   if (c < UD_MAX_MNEMONIC_CODE) {
337     return ud_mnemonics_str[c];
338   } else {
339     return "???";
340   }
341 }
342 
343 
344 /*
345  * ud_inp_init
346  *    Initializes the input system.
347  */
348 static void
ud_inp_init(struct ud * u)349 ud_inp_init(struct ud *u)
350 {
351   u->inp_hook      = NULL;
352   u->inp_buf       = NULL;
353   u->inp_buf_size  = 0;
354   u->inp_buf_index = 0;
355   u->inp_curr      = 0;
356   u->inp_ctr       = 0;
357   u->inp_end       = 0;
358   u->inp_peek      = UD_EOI;
359   UD_NON_STANDALONE(u->inp_file = NULL);
360 }
361 
362 
363 /* =============================================================================
364  * ud_inp_set_hook
365  *    Sets input hook.
366  * =============================================================================
367  */
368 void
ud_set_input_hook(register struct ud * u,int (* hook)(struct ud *))369 ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*))
370 {
371   ud_inp_init(u);
372   u->inp_hook = hook;
373 }
374 
375 /* =============================================================================
376  * ud_inp_set_buffer
377  *    Set buffer as input.
378  * =============================================================================
379  */
380 void
ud_set_input_buffer(register struct ud * u,const uint8_t * buf,size_t len)381 ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len)
382 {
383   ud_inp_init(u);
384   u->inp_buf = buf;
385   u->inp_buf_size = len;
386   u->inp_buf_index = 0;
387 }
388 
389 
390 #ifndef __UD_STANDALONE__
391 /* =============================================================================
392  * ud_input_set_file
393  *    Set FILE as input.
394  * =============================================================================
395  */
396 static int
inp_file_hook(struct ud * u)397 inp_file_hook(struct ud* u)
398 {
399   return fgetc(u->inp_file);
400 }
401 
402 void
ud_set_input_file(register struct ud * u,FILE * f)403 ud_set_input_file(register struct ud* u, FILE* f)
404 {
405   ud_inp_init(u);
406   u->inp_hook = inp_file_hook;
407   u->inp_file = f;
408 }
409 #endif /* __UD_STANDALONE__ */
410 
411 
412 /* =============================================================================
413  * ud_input_skip
414  *    Skip n input bytes.
415  * ============================================================================
416  */
417 void
ud_input_skip(struct ud * u,size_t n)418 ud_input_skip(struct ud* u, size_t n)
419 {
420   if (u->inp_end) {
421     return;
422   }
423   if (u->inp_buf == NULL) {
424     while (n--) {
425       int c = u->inp_hook(u);
426       if (c == UD_EOI) {
427         goto eoi;
428       }
429     }
430     return;
431   } else {
432     if (n > u->inp_buf_size ||
433         u->inp_buf_index > u->inp_buf_size - n) {
434       u->inp_buf_index = u->inp_buf_size;
435       goto eoi;
436     }
437     u->inp_buf_index += n;
438     return;
439   }
440 eoi:
441   u->inp_end = 1;
442   UDERR(u, "cannot skip, eoi received\b");
443   return;
444 }
445 
446 
447 /* =============================================================================
448  * ud_input_end
449  *    Returns non-zero on end-of-input.
450  * =============================================================================
451  */
452 int
ud_input_end(const struct ud * u)453 ud_input_end(const struct ud *u)
454 {
455   return u->inp_end;
456 }
457 
458 /* vim:set ts=2 sw=2 expandtab */
459