Home | History | Annotate | Download | only in DWARF
      1 //===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "DWARFLocationDescription.h"
     11 #include "DWARFDefines.h"
     12 #include "lldb/lldb-private.h"
     13 #include "lldb/Core/Stream.h"
     14 
     15 
     16 using namespace lldb_private;
     17 
     18 static int print_dwarf_exp_op (Stream &s, const DataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
     19 
     20 int
     21 print_dwarf_expression (Stream &s,
     22                         const DataExtractor& data,
     23                         int address_size,
     24                         int dwarf_ref_size,
     25                         bool location_expression)
     26 {
     27     int op_count = 0;
     28     lldb::offset_t offset = 0;
     29     while (data.ValidOffset(offset))
     30     {
     31         if (location_expression && op_count > 0)
     32         {
     33             //  err (baton, "Dwarf location expressions may only have one operand!");
     34             return 1;
     35         }
     36         if (op_count > 0)
     37         {
     38             s.PutCString(", ");
     39         }
     40         if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
     41             return 1;
     42         op_count++;
     43     }
     44 
     45     return 0;
     46 }
     47 
     48 static int
     49 print_dwarf_exp_op (Stream &s,
     50                     const DataExtractor& data,
     51                     lldb::offset_t *offset_ptr,
     52                     int address_size,
     53                     int dwarf_ref_size)
     54 {
     55     uint8_t opcode = data.GetU8(offset_ptr);
     56     DRC_class opcode_class;
     57     uint64_t  uint;
     58     int64_t   sint;
     59 
     60     int size;
     61 
     62     opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
     63 
     64     s.Printf("%s ", DW_OP_value_to_name (opcode));
     65 
     66     /* Does this take zero parameters?  If so we can shortcut this function.  */
     67     if (opcode_class == DRC_ZEROOPERANDS)
     68         return 0;
     69 
     70     if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
     71     {
     72         uint = data.GetULEB128(offset_ptr);
     73         sint = data.GetSLEB128(offset_ptr);
     74         s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
     75         return 0;
     76     }
     77     if (opcode_class != DRC_ONEOPERAND)
     78     {
     79         s.Printf("UNKNOWN OP %u", opcode);
     80         return 1;
     81     }
     82 
     83     switch (opcode)
     84     {
     85         case DW_OP_addr:    size = address_size;    break;
     86         case DW_OP_const1u: size = 1;               break;
     87         case DW_OP_const1s: size = -1;              break;
     88         case DW_OP_const2u: size = 2;               break;
     89         case DW_OP_const2s: size = -2;              break;
     90         case DW_OP_const4u: size = 4;               break;
     91         case DW_OP_const4s: size = -4;              break;
     92         case DW_OP_const8u: size = 8;               break;
     93         case DW_OP_const8s: size = -8;              break;
     94         case DW_OP_constu:  size = 128;             break;
     95         case DW_OP_consts:  size = -128;            break;
     96         case DW_OP_fbreg:   size = -128;            break;
     97         case DW_OP_breg0:
     98         case DW_OP_breg1:
     99         case DW_OP_breg2:
    100         case DW_OP_breg3:
    101         case DW_OP_breg4:
    102         case DW_OP_breg5:
    103         case DW_OP_breg6:
    104         case DW_OP_breg7:
    105         case DW_OP_breg8:
    106         case DW_OP_breg9:
    107         case DW_OP_breg10:
    108         case DW_OP_breg11:
    109         case DW_OP_breg12:
    110         case DW_OP_breg13:
    111         case DW_OP_breg14:
    112         case DW_OP_breg15:
    113         case DW_OP_breg16:
    114         case DW_OP_breg17:
    115         case DW_OP_breg18:
    116         case DW_OP_breg19:
    117         case DW_OP_breg20:
    118         case DW_OP_breg21:
    119         case DW_OP_breg22:
    120         case DW_OP_breg23:
    121         case DW_OP_breg24:
    122         case DW_OP_breg25:
    123         case DW_OP_breg26:
    124         case DW_OP_breg27:
    125         case DW_OP_breg28:
    126         case DW_OP_breg29:
    127         case DW_OP_breg30:
    128         case DW_OP_breg31:
    129             size = -128; break;
    130         case DW_OP_pick:
    131             size = 1;       break;
    132         case DW_OP_deref_size:
    133             size = 1;       break;
    134         case DW_OP_xderef_size:
    135             size = 1;       break;
    136         case DW_OP_plus_uconst:
    137             size = 128;     break;
    138         case DW_OP_skip:
    139             size = -2;      break;
    140         case DW_OP_bra:
    141             size = -2;      break;
    142         case DW_OP_call2:
    143             size = 2;       break;
    144         case DW_OP_call4:
    145             size = 4;       break;
    146         case DW_OP_call_ref:
    147             size = dwarf_ref_size;  break;
    148         case DW_OP_piece:
    149             size = 128; break;
    150         case DW_OP_regx:
    151             size = 128; break;
    152         default:
    153             s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
    154             return 1;
    155     }
    156 
    157     switch (size)
    158     {
    159     case -1:    sint = (int8_t)     data.GetU8(offset_ptr);     s.Printf("%+" PRIi64, sint); break;
    160     case -2:    sint = (int16_t)    data.GetU16(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
    161     case -4:    sint = (int32_t)    data.GetU32(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
    162     case -8:    sint = (int64_t)    data.GetU64(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
    163     case -128:  sint = data.GetSLEB128(offset_ptr);             s.Printf("%+" PRIi64, sint); break;
    164     case 1:     uint = data.GetU8(offset_ptr);                  s.Printf("0x%2.2" PRIx64, uint); break;
    165     case 2:     uint = data.GetU16(offset_ptr);                 s.Printf("0x%4.4" PRIx64, uint); break;
    166     case 4:     uint = data.GetU32(offset_ptr);                 s.Printf("0x%8.8" PRIx64, uint); break;
    167     case 8:     uint = data.GetU64(offset_ptr);                 s.Printf("0x%16.16" PRIx64, uint); break;
    168     case 128:   uint = data.GetULEB128(offset_ptr);             s.Printf("0x%" PRIx64, uint); break;
    169     }
    170 
    171     return 0;
    172 }
    173