xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_expr.c (revision 8a2b682e57a046b828f37bcde1776f131ef4629f)
1 /*
2 
3   Copyright (C) 2000,2004,2006 Silicon Graphics, Inc.  All Rights Reserved.
4   Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of version 2.1 of the GNU Lesser General Public License
8   as published by the Free Software Foundation.
9 
10   This program is distributed in the hope that it would be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 
14   Further, this software is distributed without any warranty that it is
15   free of the rightful claim of any third person regarding infringement
16   or the like.  Any license provided herein, whether implied or
17   otherwise, applies only to this software file.  Patent licenses, if
18   any, provided herein do not apply to combinations of this program with
19   other software, or any other product whatsoever.
20 
21   You should have received a copy of the GNU Lesser General Public
22   License along with this program; if not, write the Free Software
23   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
24   USA.
25 
26   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
27   Mountain View, CA 94043, or:
28 
29   http://www.sgi.com
30 
31   For further information regarding this notice, see:
32 
33   http://oss.sgi.com/projects/GenInfo/NoticeExplan
34 
35 */
36 
37 
38 
39 #include "config.h"
40 #include "libdwarfdefs.h"
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include "pro_incl.h"
45 #include "pro_expr.h"
46 
47 /*
48     This function creates a new expression
49     struct that can be used to build up a
50     location expression.
51 */
52 Dwarf_P_Expr
53 dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error)
54 {
55     Dwarf_P_Expr ret_expr;
56 
57     if (dbg == NULL) {
58         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
59         return (NULL);
60     }
61 
62     ret_expr = (Dwarf_P_Expr)
63         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Expr_s));
64     if (ret_expr == NULL) {
65         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
66         return (NULL);
67     }
68 
69     ret_expr->ex_dbg = dbg;
70 
71     return (ret_expr);
72 }
73 
74 
75 Dwarf_Unsigned
76 dwarf_add_expr_gen(Dwarf_P_Expr expr,
77                    Dwarf_Small opcode,
78                    Dwarf_Unsigned val1,
79                    Dwarf_Unsigned val2, Dwarf_Error * error)
80 {
81     char encode_buffer[2 * ENCODE_SPACE_NEEDED];        /* 2* since
82                                                            used to
83                                                            concatenate
84                                                            2 leb's
85                                                            below */
86     char encode_buffer2[ENCODE_SPACE_NEEDED];
87     int res;
88     Dwarf_P_Debug dbg = expr->ex_dbg;
89 
90     /*
91        Give the buffer where the operands are first going to be
92        assembled the largest alignment. */
93     Dwarf_Unsigned operand_buffer[10];
94 
95     /*
96        Size of the byte stream buffer that needs to be memcpy-ed. */
97     int operand_size;
98 
99     /*
100        Points to the byte stream for the first operand, and finally to
101        the buffer that is memcp-ed into the Dwarf_P_Expr_s struct. */
102     Dwarf_Small *operand;
103 
104     /* Size of the byte stream for second operand. */
105     int operand2_size;
106 
107     /* Points to next byte to be written in Dwarf_P_Expr_s struct. */
108     Dwarf_Small *next_byte_ptr;
109 
110     /* Offset past the last byte written into Dwarf_P_Expr_s. */
111     int next_byte_offset;
112 
113     /* ***** BEGIN CODE ***** */
114 
115     if (expr == NULL) {
116         _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
117         return (DW_DLV_NOCOUNT);
118     }
119 
120     if (expr->ex_dbg == NULL) {
121         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
122         return (DW_DLV_NOCOUNT);
123     }
124 
125     operand = NULL;
126     operand_size = 0;
127 
128     switch (opcode) {
129     case DW_OP_reg0:
130     case DW_OP_reg1:
131     case DW_OP_reg2:
132     case DW_OP_reg3:
133     case DW_OP_reg4:
134     case DW_OP_reg5:
135     case DW_OP_reg6:
136     case DW_OP_reg7:
137     case DW_OP_reg8:
138     case DW_OP_reg9:
139     case DW_OP_reg10:
140     case DW_OP_reg11:
141     case DW_OP_reg12:
142     case DW_OP_reg13:
143     case DW_OP_reg14:
144     case DW_OP_reg15:
145     case DW_OP_reg16:
146     case DW_OP_reg17:
147     case DW_OP_reg18:
148     case DW_OP_reg19:
149     case DW_OP_reg20:
150     case DW_OP_reg21:
151     case DW_OP_reg22:
152     case DW_OP_reg23:
153     case DW_OP_reg24:
154     case DW_OP_reg25:
155     case DW_OP_reg26:
156     case DW_OP_reg27:
157     case DW_OP_reg28:
158     case DW_OP_reg29:
159     case DW_OP_reg30:
160     case DW_OP_reg31:
161         break;
162 
163     case DW_OP_breg0:
164     case DW_OP_breg1:
165     case DW_OP_breg2:
166     case DW_OP_breg3:
167     case DW_OP_breg4:
168     case DW_OP_breg5:
169     case DW_OP_breg6:
170     case DW_OP_breg7:
171     case DW_OP_breg8:
172     case DW_OP_breg9:
173     case DW_OP_breg10:
174     case DW_OP_breg11:
175     case DW_OP_breg12:
176     case DW_OP_breg13:
177     case DW_OP_breg14:
178     case DW_OP_breg15:
179     case DW_OP_breg16:
180     case DW_OP_breg17:
181     case DW_OP_breg18:
182     case DW_OP_breg19:
183     case DW_OP_breg20:
184     case DW_OP_breg21:
185     case DW_OP_breg22:
186     case DW_OP_breg23:
187     case DW_OP_breg24:
188     case DW_OP_breg25:
189     case DW_OP_breg26:
190     case DW_OP_breg27:
191     case DW_OP_breg28:
192     case DW_OP_breg29:
193     case DW_OP_breg30:
194     case DW_OP_breg31:
195         res = _dwarf_pro_encode_signed_leb128_nm(val1,
196                                                  &operand_size,
197                                                  encode_buffer,
198                                                  sizeof(encode_buffer));
199         if (res != DW_DLV_OK) {
200             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
201             return (DW_DLV_NOCOUNT);
202         }
203         operand = (Dwarf_Small *) encode_buffer;
204         break;
205 
206     case DW_OP_regx:
207         res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
208                                           encode_buffer,
209                                           sizeof(encode_buffer));
210         if (res != DW_DLV_OK) {
211             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
212             return (DW_DLV_NOCOUNT);
213         }
214         operand = (Dwarf_Small *) encode_buffer;
215         break;
216 
217     case DW_OP_lit0:
218     case DW_OP_lit1:
219     case DW_OP_lit2:
220     case DW_OP_lit3:
221     case DW_OP_lit4:
222     case DW_OP_lit5:
223     case DW_OP_lit6:
224     case DW_OP_lit7:
225     case DW_OP_lit8:
226     case DW_OP_lit9:
227     case DW_OP_lit10:
228     case DW_OP_lit11:
229     case DW_OP_lit12:
230     case DW_OP_lit13:
231     case DW_OP_lit14:
232     case DW_OP_lit15:
233     case DW_OP_lit16:
234     case DW_OP_lit17:
235     case DW_OP_lit18:
236     case DW_OP_lit19:
237     case DW_OP_lit20:
238     case DW_OP_lit21:
239     case DW_OP_lit22:
240     case DW_OP_lit23:
241     case DW_OP_lit24:
242     case DW_OP_lit25:
243     case DW_OP_lit26:
244     case DW_OP_lit27:
245     case DW_OP_lit28:
246     case DW_OP_lit29:
247     case DW_OP_lit30:
248     case DW_OP_lit31:
249         break;
250 
251     case DW_OP_addr:
252         _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
253         return (DW_DLV_NOCOUNT);
254 
255     case DW_OP_const1u:
256     case DW_OP_const1s:
257         operand = (Dwarf_Small *) & operand_buffer[0];
258         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 1);
259         operand_size = 1;
260         break;
261 
262     case DW_OP_const2u:
263     case DW_OP_const2s:
264         operand = (Dwarf_Small *) & operand_buffer[0];
265         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2);
266         operand_size = 2;
267         break;
268 
269     case DW_OP_const4u:
270     case DW_OP_const4s:
271         operand = (Dwarf_Small *) & operand_buffer[0];
272         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4);
273         operand_size = 4;
274         break;
275 
276     case DW_OP_const8u:
277     case DW_OP_const8s:
278         operand = (Dwarf_Small *) & operand_buffer[0];
279         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 8);
280         operand_size = 8;
281         break;
282 
283     case DW_OP_constu:
284         res = _dwarf_pro_encode_leb128_nm(val1,
285                                           &operand_size,
286                                           encode_buffer,
287                                           sizeof(encode_buffer));
288         if (res != DW_DLV_OK) {
289             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
290             return (DW_DLV_NOCOUNT);
291         }
292         operand = (Dwarf_Small *) encode_buffer;
293         break;
294 
295     case DW_OP_consts:
296         res = _dwarf_pro_encode_signed_leb128_nm(val1,
297                                                  &operand_size,
298                                                  encode_buffer,
299                                                  sizeof(encode_buffer));
300         if (res != DW_DLV_OK) {
301             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
302             return (DW_DLV_NOCOUNT);
303         }
304         operand = (Dwarf_Small *) encode_buffer;
305         break;
306 
307     case DW_OP_fbreg:
308         res = _dwarf_pro_encode_signed_leb128_nm(val1,
309                                                  &operand_size,
310                                                  encode_buffer,
311                                                  sizeof(encode_buffer));
312         if (res != DW_DLV_OK) {
313             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
314             return (DW_DLV_NOCOUNT);
315         }
316         operand = (Dwarf_Small *) encode_buffer;
317         break;
318 
319     case DW_OP_bregx:
320         res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
321                                           encode_buffer,
322                                           sizeof(encode_buffer));
323         if (res != DW_DLV_OK) {
324             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
325             return (DW_DLV_NOCOUNT);
326         }
327         operand = (Dwarf_Small *) encode_buffer;
328         /* put this one directly into 'operand' at tail of prev value */
329         res = _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size,
330                                                  ((char *) operand) +
331                                                  operand_size,
332                                                  sizeof
333                                                  (encode_buffer2));
334         if (res != DW_DLV_OK) {
335             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
336             return (DW_DLV_NOCOUNT);
337         }
338         operand_size += operand2_size;
339 
340     case DW_OP_dup:
341     case DW_OP_drop:
342         break;
343 
344     case DW_OP_pick:
345         operand = (Dwarf_Small *) & operand_buffer[0];
346         WRITE_UNALIGNED(dbg, operand, (const void *) &val1,
347                         sizeof(val1), 1);
348         operand_size = 1;
349         break;
350 
351     case DW_OP_over:
352     case DW_OP_swap:
353     case DW_OP_rot:
354     case DW_OP_deref:
355     case DW_OP_xderef:
356         break;
357 
358     case DW_OP_deref_size:
359     case DW_OP_xderef_size:
360         operand = (Dwarf_Small *) & operand_buffer[0];
361         WRITE_UNALIGNED(dbg, operand, (const void *) &val1,
362                         sizeof(val1), 1);
363         operand_size = 1;
364         break;
365 
366     case DW_OP_abs:
367     case DW_OP_and:
368     case DW_OP_div:
369     case DW_OP_minus:
370     case DW_OP_mod:
371     case DW_OP_mul:
372     case DW_OP_neg:
373     case DW_OP_not:
374     case DW_OP_or:
375     case DW_OP_plus:
376         break;
377 
378     case DW_OP_plus_uconst:
379         res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
380                                           encode_buffer,
381                                           sizeof(encode_buffer));
382         if (res != DW_DLV_OK) {
383             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
384             return (DW_DLV_NOCOUNT);
385         }
386         operand = (Dwarf_Small *) encode_buffer;
387         break;
388 
389     case DW_OP_shl:
390     case DW_OP_shr:
391     case DW_OP_shra:
392     case DW_OP_xor:
393         break;
394 
395     case DW_OP_le:
396     case DW_OP_ge:
397     case DW_OP_eq:
398     case DW_OP_lt:
399     case DW_OP_gt:
400     case DW_OP_ne:
401         break;
402 
403     case DW_OP_skip:
404     case DW_OP_bra:
405         /* FIX: unhandled! OP_bra, OP_skip! */
406         _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
407         return (DW_DLV_NOCOUNT);
408 
409     case DW_OP_piece:
410         res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
411                                           encode_buffer,
412                                           sizeof(encode_buffer));
413         if (res != DW_DLV_OK) {
414             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
415             return (DW_DLV_NOCOUNT);
416         }
417         operand = (Dwarf_Small *) encode_buffer;
418         break;
419 
420     case DW_OP_nop:
421         break;
422     case DW_OP_push_object_address:     /* DWARF3 */
423         break;
424     case DW_OP_call2:           /* DWARF3 */
425         operand = (Dwarf_Small *) & operand_buffer[0];
426         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2);
427         operand_size = 2;
428         break;
429 
430     case DW_OP_call4:           /* DWARF3 */
431         operand = (Dwarf_Small *) & operand_buffer[0];
432         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4);
433         operand_size = 4;
434         break;
435 
436     case DW_OP_call_ref:        /* DWARF3 */
437         operand = (Dwarf_Small *) & operand_buffer[0];
438         WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1),
439                         dbg->de_offset_size);
440         operand_size = dbg->de_offset_size;
441         break;
442     case DW_OP_form_tls_address:        /* DWARF3f */
443         break;
444     case DW_OP_call_frame_cfa:  /* DWARF3f */
445         break;
446     case DW_OP_bit_piece:       /* DWARF3f */
447         res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
448                                           encode_buffer,
449                                           sizeof(encode_buffer));
450         if (res != DW_DLV_OK) {
451             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
452             return (DW_DLV_NOCOUNT);
453         }
454         operand = (Dwarf_Small *) encode_buffer;
455         /* put this one directly into 'operand' at tail of prev value */
456         res = _dwarf_pro_encode_leb128_nm(val2, &operand2_size,
457                                           ((char *) operand) +
458                                           operand_size,
459                                           sizeof(encode_buffer2));
460         if (res != DW_DLV_OK) {
461             _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
462             return (DW_DLV_NOCOUNT);
463         }
464         operand_size += operand2_size;
465 	break;
466 
467     default:
468         _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
469         return (DW_DLV_NOCOUNT);
470     }
471 
472     next_byte_offset = expr->ex_next_byte_offset + operand_size + 1;
473 
474     if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
475         _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
476         return (DW_DLV_NOCOUNT);
477     }
478 
479     next_byte_ptr =
480         &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;
481 
482     *next_byte_ptr = opcode;
483     next_byte_ptr++;
484     memcpy(next_byte_ptr, operand, operand_size);
485 
486     expr->ex_next_byte_offset = next_byte_offset;
487     return (next_byte_offset);
488 }
489 
490 Dwarf_Unsigned
491 dwarf_add_expr_addr_b(Dwarf_P_Expr expr,
492                       Dwarf_Unsigned addr,
493                       Dwarf_Unsigned sym_index, Dwarf_Error * error)
494 {
495     Dwarf_P_Debug dbg;
496     Dwarf_Small *next_byte_ptr;
497     Dwarf_Unsigned next_byte_offset;
498     int upointer_size;
499 
500     if (expr == NULL) {
501         _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
502         return (DW_DLV_NOCOUNT);
503     }
504 
505     dbg = expr->ex_dbg;
506     if (dbg == NULL) {
507         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
508         return (DW_DLV_NOCOUNT);
509     }
510 
511     upointer_size = dbg->de_pointer_size;
512     next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1;
513     if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
514         _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
515         return (DW_DLV_NOCOUNT);
516     }
517 
518     next_byte_ptr =
519         &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;
520 
521     *next_byte_ptr = DW_OP_addr;
522     next_byte_ptr++;
523     WRITE_UNALIGNED(dbg, next_byte_ptr, (const void *) &addr,
524                     sizeof(addr), upointer_size);
525 
526     if (expr->ex_reloc_offset != 0) {
527         _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR);
528         return (DW_DLV_NOCOUNT);
529     }
530 
531     expr->ex_reloc_sym_index = sym_index;
532     expr->ex_reloc_offset = expr->ex_next_byte_offset + 1;
533 
534     expr->ex_next_byte_offset = next_byte_offset;
535     return (next_byte_offset);
536 }
537 
538 Dwarf_Unsigned
539 dwarf_add_expr_addr(Dwarf_P_Expr expr,
540                     Dwarf_Unsigned addr,
541                     Dwarf_Signed sym_index, Dwarf_Error * error)
542 {
543     return
544         dwarf_add_expr_addr_b(expr, addr, (Dwarf_Unsigned) sym_index,
545                               error);
546 }
547 
548 
549 Dwarf_Unsigned
550 dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error)
551 {
552     if (expr == NULL) {
553         _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
554         return (DW_DLV_NOCOUNT);
555     }
556 
557     if (expr->ex_dbg == NULL) {
558         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
559         return (DW_DLV_NOCOUNT);
560     }
561 
562     return (expr->ex_next_byte_offset);
563 }
564 
565 void
566 dwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error)
567 {
568    if (expr == NULL) {
569       _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
570       return;
571    }
572    expr->ex_next_byte_offset=0;
573 }
574 
575 
576 Dwarf_Addr
577 dwarf_expr_into_block(Dwarf_P_Expr expr,
578                       Dwarf_Unsigned * length, Dwarf_Error * error)
579 {
580     if (expr == NULL) {
581         _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
582         return (DW_DLV_BADADDR);
583     }
584 
585     if (expr->ex_dbg == NULL) {
586         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
587         return (DW_DLV_BADADDR);
588     }
589 
590     if (length != NULL)
591         *length = expr->ex_next_byte_offset;
592     /* The following cast from pointer to integer is ok as long as
593        Dwarf_Addr is at least as large as a pointer. Which is a
594        requirement of libdwarf so must be satisfied (some compilers
595        emit a warning about the following line). */
596     return ((Dwarf_Addr)(uintptr_t) &(expr->ex_byte_stream[0]));
597 }
598