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*/
52Dwarf_P_Expr
53dwarf_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
75Dwarf_Unsigned
76dwarf_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
490Dwarf_Unsigned
491dwarf_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
538Dwarf_Unsigned
539dwarf_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
549Dwarf_Unsigned
550dwarf_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
565void
566dwarf_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
576Dwarf_Addr
577dwarf_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