+/** \brief Convert libdw location expresion elment into native one (or NULL in some cases) */
+static dw_location_t MC_dwarf_get_expression_element(Dwarf_Op* op) {
+ dw_location_t element = xbt_new0(s_dw_location_t, 1);
+ uint8_t atom = op->atom;
+ if (atom >= DW_OP_reg0 && atom<= DW_OP_reg31) {
+ element->type = e_dw_register;
+ element->location.reg = atom - DW_OP_reg0;
+ }
+ else if (atom >= DW_OP_breg0 && atom<= DW_OP_breg31) {
+ element->type = e_dw_bregister_op;
+ element->location.reg = atom - DW_OP_breg0;
+ element->location.breg_op.offset = op->number;
+ }
+ else if (atom >= DW_OP_lit0 && atom<= DW_OP_lit31) {
+ element->type = e_dw_lit;
+ element->location.reg = atom - DW_OP_lit0;
+ }
+ else switch (atom) {
+ case DW_OP_fbreg:
+ element->type = e_dw_fbregister_op;
+ element->location.fbreg_op = op->number;
+ break;
+ case DW_OP_piece:
+ element->type = e_dw_piece;
+ element->location.piece = op->number;
+ break;
+ case DW_OP_plus_uconst:
+ element->type = e_dw_plus_uconst;
+ element->location.plus_uconst = op->number;
+ break;
+ case DW_OP_abs:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("abs");
+ break;
+ case DW_OP_and:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("and");
+ break;
+ case DW_OP_div:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("div");
+ break;
+ case DW_OP_minus:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("minus");
+ break;
+ case DW_OP_mod:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("mod");
+ break;
+ case DW_OP_mul:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("mul");
+ break;
+ case DW_OP_neg:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("neg");
+ break;
+ case DW_OP_not:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("not");
+ break;
+ case DW_OP_or:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("or");
+ break;
+ case DW_OP_plus:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("plus");
+ break;
+
+ case DW_OP_stack_value:
+ // Why nothing here?
+ xbt_free(element);
+ return NULL;
+
+ case DW_OP_deref_size:
+ element->type = e_dw_deref;
+ element->location.deref_size = (unsigned int short) op->number;
+ break;
+ case DW_OP_deref:
+ element->type = e_dw_deref;
+ element->location.deref_size = sizeof(void *);
+ break;
+ case DW_OP_constu:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_consts:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+
+ case DW_OP_const1u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const2u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 2;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const4u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 4;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const8u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 8;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+
+ case DW_OP_const1s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const2s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 2;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const4s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 4;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const8s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 8;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ default:
+ element->type = e_dw_unsupported;
+ break;
+ }
+ return element;
+}
+
+/** \brief Convert libdw location expresion into native one */
+static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len) {
+ dw_location_t loc = xbt_new0(s_dw_location_t, 1);
+ loc->type = e_dw_compose;
+ loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
+
+ int i;
+ for (i=0; i!=len; ++i) {
+ dw_location_t element = MC_dwarf_get_expression_element(expr+i);
+ if (element)
+ xbt_dynar_push(loc->location.compose, &element);
+ }
+
+ return loc;
+}