Beispiel #1
0
/* print data in .debug_loc 
   There is no guarantee this will work because we are assuming
   that all bytes are valid loclist data, that there are no
   odd padding or garbage bytes.  In normal use one gets
   into here via an offset from .debug_info, so it could be
   that bytes not referenced from .debug_info are garbage
   or even zero padding.  So this can fail (error off) as such bytes
   can lead dwarf_get_loclist_entry() astray.

   It's also wrong because we don't know what CU or frame each
   loclist is from, so we don't know the address_size for sure.
*/
extern void
print_locs(Dwarf_Debug dbg)
{
    Dwarf_Unsigned offset = 0;
    Dwarf_Addr hipc_offset = 0;
    Dwarf_Addr lopc_offset = 0;
    Dwarf_Ptr data = 0;
    Dwarf_Unsigned entry_len = 0;
    Dwarf_Unsigned next_entry = 0;
    struct esb_s  exprstring;
    int index = 0; 
    int lres = 0;
    int fres = 0;

    /* This is sometimes wrong, we need a frame-specific size. */
    Dwarf_Half address_size = 0;

    current_section_id = DEBUG_LOC;

    /* Do nothing if not printing. */
    if (!do_print_dwarf) {
        return;
    }

    fres = dwarf_get_address_size(dbg, &address_size, &err);
    if (fres != DW_DLV_OK) {
        print_error(dbg, "dwarf_get_address_size", fres, err);
    }

    printf("\n.debug_loc");
  
    printf("\nFormat <i o b e l>: "
        "index section-offset begin-addr end-addr length-of-block-entry\n");
    esb_constructor(&exprstring);
    while ((lres = dwarf_get_loclist_entry(dbg, offset,
        &hipc_offset, &lopc_offset,
        &data, &entry_len,
        &next_entry,
        &err)) == DW_DLV_OK) {
        get_string_from_locs(dbg,data,entry_len,address_size,
            &exprstring);
        /* Display offsets */
        if (display_offsets) {
            ++index;
            printf(" <iobel> [%8d] 0x%" DW_PR_XZEROS DW_PR_DUx,
                index, offset);
            if(verbose) {
                printf(" <expr-off 0x%"  DW_PR_XZEROS  DW_PR_DUx ">",
                    next_entry - entry_len);
            }
        }
        printf(" 0x%"  DW_PR_XZEROS  DW_PR_DUx 
            " 0x%" DW_PR_XZEROS DW_PR_DUx  
            " %8" DW_PR_DUu " %s\n",
            (Dwarf_Unsigned) lopc_offset,
            (Dwarf_Unsigned) hipc_offset,  entry_len,
            esb_get_string(&exprstring));
        esb_empty_string(&exprstring);
        offset = next_entry;
    }
    esb_destructor(&exprstring);
    if (lres == DW_DLV_ERROR) {
        print_error(dbg, "dwarf_get_loclist_entry", lres, err);
    }
}
 /*ARGSUSED*/ void
print_frame_inst_bytes(Dwarf_Debug dbg,
		       Dwarf_Ptr cie_init_inst, Dwarf_Signed len,
		       Dwarf_Signed data_alignment_factor,
		       int code_alignment_factor, Dwarf_Half addr_size,
		       struct dwconf_s *config_data)
{
    unsigned char *instp = (unsigned char *) cie_init_inst;
    Dwarf_Unsigned uval;
    Dwarf_Unsigned uval2;
    unsigned int uleblen;
    unsigned int off = 0;
    unsigned int loff = 0;
    unsigned short u16;
    unsigned int u32;
    unsigned long long u64;

    for (; len > 0;) {
	unsigned char ibyte = *instp;
	int top = ibyte & 0xc0;
	int bottom = ibyte & 0x3f;
	int delta;
	int reg;

	switch (top) {
	case DW_CFA_advance_loc:
	    delta = ibyte & 0x3f;
	    printf("\t%2u DW_CFA_advance_loc %d", off,
		   (int) (delta * code_alignment_factor));
	    if (verbose) {
		printf("  (%d * %d)", (int) delta,
		       (int) code_alignment_factor);
	    }
	    printf("\n");
	    break;
	case DW_CFA_offset:
	    loff = off;
	    reg = ibyte & 0x3f;
	    uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
	    instp += uleblen;
	    len -= uleblen;
	    off += uleblen;
	    printf("\t%2u DW_CFA_offset ", loff);
	    printreg((Dwarf_Signed) reg, config_data);
	    printf(" %lld", (signed long long)
		   (((Dwarf_Signed) uval) * data_alignment_factor));
	    if (verbose) {
		printf("  (%llu * %d)", (unsigned long long) uval,
		       (int) data_alignment_factor);
	    }
	    printf("\n");
	    break;

	case DW_CFA_restore:
	    reg = ibyte & 0x3f;
	    printf("\t%2u DW_CFA_restore \n", off);
	    printreg((Dwarf_Signed) reg, config_data);
	    printf("\n");
	    break;

	default:
	    loff = off;
	    switch (bottom) {
	    case DW_CFA_set_loc:
		/* operand is address, so need address size */
		/* which will be 4 or 8. */
		switch (addr_size) {
		case 4:
		    {
			__uint32_t v32;

			memcpy(&v32, instp + 1, addr_size);
			uval = v32;
		    }
		    break;
		case 8:
		    {
			__uint64_t v64;

			memcpy(&v64, instp + 1, addr_size);
			uval = v64;
		    }
		    break;
		default:
		    printf
			("Error: Unexpected address size %d in DW_CFA_set_loc!\n",
			 addr_size);
		    uval = 0;
		}

		instp += addr_size;
		len -= (Dwarf_Signed) addr_size;
		off += addr_size;
		printf("\t%2u DW_CFA_set_loc %llu\n",
		       loff, (unsigned long long) uval);
		break;
	    case DW_CFA_advance_loc1:
		delta = (unsigned char) *(instp + 1);
		uval2 = delta;
		instp += 1;
		len -= 1;
		off += 1;
		printf("\t%2u DW_CFA_advance_loc1 %llu\n",
		       loff, (unsigned long long) uval2);
		break;
	    case DW_CFA_advance_loc2:
		memcpy(&u16, instp + 1, 2);
		uval2 = u16;
		instp += 2;
		len -= 2;
		off += 2;
		printf("\t%2u DW_CFA_advance_loc2 %llu\n",
		       loff, (unsigned long long) uval2);
		break;
	    case DW_CFA_advance_loc4:
		memcpy(&u32, instp + 1, 4);
		uval2 = u32;
		instp += 4;
		len -= 4;
		off += 4;
		printf("\t%2u DW_CFA_advance_loc4 %llu\n",
		       loff, (unsigned long long) uval2);
		break;
	    case DW_CFA_MIPS_advance_loc8:
		memcpy(&u64, instp + 1, 8);
		uval2 = u64;
		instp += 8;
		len -= 8;
		off += 8;
		printf("\t%2u DW_CFA_MIPS_advance_loc8 %llu\n",
		       loff, (unsigned long long) uval2);
		break;
	    case DW_CFA_offset_extended:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		uval2 =
		    local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_offset_extended ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf(" %lld", (signed long long)
		       (((Dwarf_Signed) uval2) *
			data_alignment_factor));
		if (verbose) {
		    printf("  (%llu * %d)", (unsigned long long) uval2,
			   (int) data_alignment_factor);
		}
		printf("\n");
		break;

	    case DW_CFA_restore_extended:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_restore_extended ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf("\n");
		break;
	    case DW_CFA_undefined:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_undefined ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf("\n");
		break;
	    case DW_CFA_same_value:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_same_value ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf("\n");
		break;
	    case DW_CFA_register:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		uval2 =
		    local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_register ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf(" = ");
		printreg((Dwarf_Signed) uval2, config_data);
		printf("\n");
		break;
	    case DW_CFA_remember_state:
		printf("\t%2u DW_CFA_remember_state\n", loff);
		break;
	    case DW_CFA_restore_state:
		printf("\t%2u DW_CFA_restore_state\n", loff);
		break;
	    case DW_CFA_def_cfa:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		uval2 =
		    local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_def_cfa ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf(" %llu", (unsigned long long) uval2);
		printf("\n");
		break;
	    case DW_CFA_def_cfa_register:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_def_cfa_register ", loff);
		printreg((Dwarf_Signed) uval, config_data);
		printf("\n");
		break;
	    case DW_CFA_def_cfa_offset:
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		printf("\t%2u DW_CFA_def_cfa_offset %llu\n",
		       loff, (unsigned long long) uval);
		break;

	    case DW_CFA_nop:
		printf("\t%2u DW_CFA_nop\n", loff);
		break;

	    case DW_CFA_def_cfa_expression:	/* DWARF3 */
		{
		    Dwarf_Unsigned block_len =
			local_dwarf_decode_u_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf
			("\t%2u DW_CFA_def_cfa_expression expr block len %lld\n",
			 loff, (unsigned long long)
			 block_len);
		    dump_block("\t\t", (char *) instp+1,
			       (Dwarf_Signed) block_len);
                    printf("\n");
                    if(verbose) {
                      struct esb_s exprstring;
                      esb_constructor(&exprstring);
                      get_string_from_locs(dbg,
			    instp+1,block_len,&exprstring);
                      printf("\t\t%s\n",esb_get_string(&exprstring));
                      esb_destructor(&exprstring);
                    }
		    instp += block_len;
		    len -= block_len;
		    off += block_len;
		}
		break;
	    case DW_CFA_expression:	/* DWARF3 */
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		{
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		    Dwarf_Unsigned block_len =
			local_dwarf_decode_u_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf
			("\t%2u DW_CFA_expression %llu expr block len %lld\n",
			 loff, (unsigned long long) uval,
			 (unsigned long long)
			 block_len);
		    dump_block("\t\t", (char *) instp+1,
			       (Dwarf_Signed) block_len);
                    printf("\n");
                    if(verbose) {
                      struct esb_s exprstring;
                      esb_constructor(&exprstring);
                      get_string_from_locs(dbg,
			    instp+1,block_len,&exprstring);
                      printf("\t\t%s\n",esb_get_string(&exprstring));
                      esb_destructor(&exprstring);
                    }
		    instp += block_len;
		    len -= block_len;
		    off += block_len;
		}

		break;
	    case DW_CFA_cfa_offset_extended_sf:	/* DWARF3 */
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		{
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		    Dwarf_Signed sval2 =
			local_dwarf_decode_s_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf("\t%2u DW_CFA_offset_extended_sf ", loff);
		    printreg((Dwarf_Signed) uval, config_data);
		    printf(" %lld", (signed long long)
			   ((sval2) * data_alignment_factor));
		    if (verbose) {
			printf("  (%lld * %d)", (long long) sval2,
			       (int) data_alignment_factor);
		    }
		}
		printf("\n");
		break;
	    case DW_CFA_def_cfa_sf:	/* DWARF3 */
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		{
		    Dwarf_Signed sval2 =
			local_dwarf_decode_s_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf("\t%2u DW_CFA_def_cfa_sf ", loff);
		    printreg((Dwarf_Signed) uval, config_data);
		    printf(" %lld", (long long) sval2); 
                    printf(" (*data alignment factor=>%lld)",
                     (long long)(sval2*data_alignment_factor));
		}
		printf("\n");
		break;
	    case DW_CFA_def_cfa_offset_sf:	/* DWARF3 */
		{
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		    Dwarf_Signed sval =
			local_dwarf_decode_s_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf("\t%2u DW_CFA_def_cfa_offset_sf %lld (*data alignment factor=> %lld)\n",
			   loff, (long long) sval,
                           (long long)(data_alignment_factor*sval));

		}
		break;
	    case DW_CFA_val_offset:	/* DWARF3 */
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		{
		    uval2 =
			local_dwarf_decode_s_leb128(instp + 1,
						    &uleblen);
		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf("\t%2u DW_CFA_val_offset ", loff);
		    printreg((Dwarf_Signed) uval, config_data);
		    printf(" %lld", (unsigned long long)
			   (((Dwarf_Signed) uval2) *
			    data_alignment_factor));
		    if (verbose) {
			printf("  (%lld * %d)", (long long) uval2,
			       (int) data_alignment_factor);
		    }
		}
		printf("\n");

		break;
	    case DW_CFA_val_offset_sf:	/* DWARF3 */
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		{
		    Dwarf_Signed sval2 =
			local_dwarf_decode_s_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf("\t%2u DW_CFA_val_offset_sf ", loff);
		    printreg((Dwarf_Signed) uval, config_data);
		    printf(" %lld", (signed long long)
			   ((sval2) * data_alignment_factor));
		    if (verbose) {
			printf("  (%lld * %d)", (long long) sval2,
			       (int) data_alignment_factor);
		    }
		}
		printf("\n");

		break;
	    case DW_CFA_val_expression:	/* DWARF3 */
                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
		instp += uleblen;
		len -= uleblen;
		off += uleblen;
		{
		    Dwarf_Unsigned block_len =
			local_dwarf_decode_u_leb128(instp + 1,
						    &uleblen);

		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;
		    printf
			("\t%2u DW_CFA_val_expression %llu expr block len %lld\n",
			 loff, (unsigned long long) uval,
			 (unsigned long long)
			 block_len);
		    dump_block("\t\t", (char *) instp+1,
			       (Dwarf_Signed) block_len);
                    printf("\n");
                    if(verbose) {
                      struct esb_s exprstring;
                      esb_constructor(&exprstring);
                      get_string_from_locs(dbg,
			    instp+1,block_len,&exprstring);
                      printf("\t\t%s\n",esb_get_string(&exprstring));
                      esb_destructor(&exprstring);
                    }
		    instp += block_len;
		    len -= block_len;
		    off += block_len;
		}


		break;


#ifdef DW_CFA_GNU_window_save
	    case DW_CFA_GNU_window_save:{
		    /* no information: this just tells unwinder to
		       restore the window registers from the previous
		       frame's window save area */
		    printf("\t%2u DW_CFA_GNU_window_save \n", loff);
		    break;
		}
#endif
#ifdef DW_CFA_GNU_negative_offset_extended
	    case DW_CFA_GNU_negative_offset_extended:{
		    printf
			("\t%2u DW_CFA_GNU_negative_offset_extended \n",
			 loff);
		}
#endif
#ifdef  DW_CFA_GNU_args_size
		/* single uleb128 is the current arg area size in
		   bytes. no register exists yet to save this in */
	    case DW_CFA_GNU_args_size:{
		    Dwarf_Unsigned lreg;

                    /* instp is always 1 byte back, so we need +1
			when we use it. See the final increment
                        of this for loop. */
		    lreg =
			local_dwarf_decode_u_leb128(instp + 1,
						    &uleblen);
		    printf
			("\t%2u DW_CFA_GNU_args_size arg size: %llu\n",
			 loff, (unsigned long long) lreg);
		    instp += uleblen;
		    len -= uleblen;
		    off += uleblen;

		    break;
		}
#endif

	    default:
		printf("\t%u Unexpected op 0x%x: \n",
		       loff, (unsigned int) bottom);
		len = 0;
		break;
	    }
	}
	instp++;
	len--;
	off++;
    }
}
Beispiel #3
0
/* print data in .debug_loc
   There is no guarantee this will work because we are assuming
   that all bytes are valid loclist data, that there are no
   odd padding or garbage bytes.  In normal use one gets
   into here via an offset from .debug_info, so it could be
   that bytes not referenced from .debug_info are garbage
   or even zero padding.  So this can fail (error off) as such bytes
   can lead dwarf_get_loclist_entry() astray.

   It's also wrong because we don't know what CU or frame each
   loclist is from, so we don't know the address_size for sure.
*/
extern void
print_locs(Dwarf_Debug dbg)
{
    Dwarf_Unsigned offset = 0;
    Dwarf_Addr hipc_offset = 0;
    Dwarf_Addr lopc_offset = 0;
    Dwarf_Ptr data = 0;
    Dwarf_Unsigned entry_len = 0;
    Dwarf_Unsigned next_entry = 0;
    int index = 0;
    int lres = 0;
    int fres = 0;
    Dwarf_Half address_size = 0;
    Dwarf_Half offset_size = 0;
    Dwarf_Half version = 2; /* FAKE */
    Dwarf_Error err = 0;
    struct esb_s  exprstring;
    unsigned loopct = 0;

    esb_constructor(&exprstring);
    glflags.current_section_id = DEBUG_LOC;

    /* Do nothing if not printing. */
    if (!glflags.gf_do_print_dwarf) {
        return;
    }
    if(!glflags.gf_use_old_dwarf_loclist) {
        printf("\n");
        printf("Printing location lists with -c is no longer supported\n");
        return;
    }

    fres = dwarf_get_address_size(dbg, &address_size, &err);
    if (fres != DW_DLV_OK) {
        print_error(dbg, "dwarf_get_address_size", fres, err);
    }
    fres = dwarf_get_offset_size(dbg, &offset_size, &err);
    if (fres != DW_DLV_OK) {
        print_error(dbg, "dwarf_get_address_size", fres, err);
    }
#if 0
    /*  This print code not needed as cannot be safely used
        and uses old interface. */
    {
        struct esb_s truename;
        char buf[DWARF_SECNAME_BUFFER_SIZE];

        esb_constructor_fixed(&truename,buf,sizeof(buf));
        get_true_section_name(dbg,".debug_loc",
            &truename,TRUE);
        printf("\n%s\n",sanitized(esb_get_string(&truename)));
        esb_destructor(&truename);
    }
#endif

    printf("Format <i o b e l>: "
        "index section-offset begin-addr end-addr length-of-block-entry\n");
    /*  Pre=October 2015 version. */
    for (loopct = 0;
        (lres = dwarf_get_loclist_entry(dbg, offset,
        &hipc_offset, &lopc_offset,
        &data, &entry_len,
        &next_entry,
        &err)) == DW_DLV_OK;
        ++loopct) {
        get_string_from_locs(dbg,data,entry_len,address_size,
            offset_size,
            version,
            &exprstring);
        /* Display offsets */
        if (!loopct) {
            /*  This print code not needed as cannot be safely used
                and uses old interface. */
            print_secname(dbg,".debug_loc");
        }
        if (glflags.gf_display_offsets) {
            ++index;
            printf("  <iobel> [%8d] 0x%" DW_PR_XZEROS DW_PR_DUx,
                index, offset);
            if (glflags.verbose) {
                printf(" <expr-off 0x%"  DW_PR_XZEROS  DW_PR_DUx ">",
                    next_entry - entry_len);
            }
        }
        printf(" 0x%"  DW_PR_XZEROS  DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " %8" DW_PR_DUu " %s\n",
            (Dwarf_Unsigned) lopc_offset,
            (Dwarf_Unsigned) hipc_offset,  entry_len,
            esb_get_string(&exprstring));
        esb_empty_string(&exprstring);
        offset = next_entry;
    }
    if (!loopct) {
        /*  This print code not needed as cannot be safely used
            and uses old interface. */
        print_secname(dbg,".debug_loc");
    }
    esb_destructor(&exprstring);
    if (lres == DW_DLV_ERROR) {
        print_error(dbg, "dwarf_get_loclist_entry", lres, err);
    }
}
static void
print_one_frame_reg_col(Dwarf_Debug dbg,
                        Dwarf_Unsigned rule_id,
                        Dwarf_Small value_type,
                        Dwarf_Unsigned reg_used,
                        struct dwconf_s *config_data,
                        Dwarf_Signed offset_relevant,
                        Dwarf_Signed offset, 
                        Dwarf_Ptr block_ptr)
{
    char *type_title = "";
    int print_type_title = 1;

    if (config_data->cf_interface_number == 2)
	print_type_title = 0;

    switch (value_type) {
    case DW_EXPR_OFFSET:
	type_title = "off";
	goto preg2;
    case DW_EXPR_VAL_OFFSET:
	type_title = "valoff";
      preg2:
	if (reg_used == config_data->cf_initial_rule_value) {
	    break;
	}
	if (print_type_title)
	    printf("<%s ", type_title);
	printreg((Dwarf_Signed) rule_id, config_data);
	printf("=");
	if (offset_relevant == 0) {
	    printreg((Dwarf_Signed) reg_used, config_data);
	    printf(" ");
	} else {
	    printf("%02lld", offset);
	    printf("(");
	    printreg((Dwarf_Signed) reg_used, config_data);
	    printf(") ");
	}
	if (print_type_title)
	    printf("%s", "> ");
	break;
    case DW_EXPR_EXPRESSION:
	type_title = "expr";
	goto pexp2;
    case DW_EXPR_VAL_EXPRESSION:
	type_title = "valexpr";
      pexp2:
	if (print_type_title)
	    printf("<%s ", type_title);
	printreg((Dwarf_Signed) rule_id, config_data);
	printf("=");
	printf("expr-block-len=%lld", (long long) offset);
	if (print_type_title)
	    printf("%s", "> ");
	if (verbose) {
	    char pref[40];

	    strcpy(pref, "<");
	    strcat(pref, type_title);
	    strcat(pref, "bytes:");
	    dump_block(pref, block_ptr, offset);
	    printf("%s", "> ");
            if(verbose) {
                      struct esb_s exprstring;
                      esb_constructor(&exprstring);
                      get_string_from_locs(dbg,
			    block_ptr,offset,&exprstring);
                      printf("<expr:%s>",esb_get_string(&exprstring));
                      esb_destructor(&exprstring);
            }
	}
	break;
    default:
	printf("Internal error in libdwarf, value type %d\n",
	       value_type);
	exit(1);
    }
    return;
}