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