data += bytes_read;
state_machine_regs.column = adv;
if (di->ddump_line)
- VG_(printf)(" DWARF2-line: set_column\n");
+ VG_(printf)(" Set column to %d\n", (Int)adv);
break;
case DW_LNS_negate_stmt:
UInt acode, abcode;
ULong atoffs, blklen;
Int level;
- UShort ver;
+ /* UShort ver; */
UChar addr_size;
UChar* p = unitblock_img;
p += ui->dw64 ? 12 : 4;
/* version should be 2, 3 or 4 */
- ver = *((UShort*)p);
+ /* ver = *((UShort*)p); */
p += 2;
/* get offset in abbrev */
/* TJH 27 Apr 10: in DWARF 4 lineptr (and loclistptr,macptr,
rangelistptr classes) use FORM_sec_offset which is 64 bits
in 64 bit DWARF and 32 bits in 32 bit DWARF. */
+ /* JRS 20 Apr 11: LLVM-2.9 encodes DW_AT_stmt_list using
+ FORM_addr rather than the FORM_data4 that GCC uses. Hence
+ handle FORM_addr too. */
switch( form ) {
/* Those cases extract the data properly */
case 0x05: /* FORM_data2 */ cval = *((UShort*)p); p +=2; break;
} else {
cval = *((UInt*)p); p += 4;
}; break;
+
+ case 0x07: /* FORM_data8 */ if (ui->dw64) cval = *((ULong*)p);
+ p += 8; break;
+ /* perhaps should assign
+ unconditionally to cval? */
+
/* TODO : Following ones just skip data - implement if you need */
case 0x01: /* FORM_addr */ p += addr_size; break;
case 0x03: /* FORM_block2 */ p += *((UShort*)p) + 2; break;
case 0x04: /* FORM_block4 */ p += *((UInt*)p) + 4; break;
- case 0x07: /* FORM_data8 */ if (ui->dw64) cval = *((ULong*)p);
- p += 8; break;
- /* perhaps should assign unconditionally to cval? */
case 0x09: /* FORM_block */ p += read_leb128U( &p ); break;
case 0x0a: /* FORM_block1 */ p += *p + 1; break;
case 0x0c: /* FORM_flag */ p++; break;
# define FP_REG 6
# define SP_REG 7
# define RA_REG_DEFAULT 16
+#elif defined(VGP_s390x_linux)
+# define FP_REG 11 // sometimes s390 has a frame pointer in r11
+# define SP_REG 15 // stack is always r15
+# define RA_REG_DEFAULT 14 // the return address is in r14
#elif defined(VGP_x86_l4re)
# define FP_REG 5
# define SP_REG 4
/* ctx->state[j].reg[13].tag = RR_Same; */
ctx->state[j].reg[14].tag = RR_Same;
ctx->state[j].reg[12].tag = RR_Same;
+ ctx->state[j].reg[7].tag = RR_Same;
/* this can't be right though: R12 (IP) isn't callee saved. */
# endif
}
else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
si->cfa_off = ctxs->cfa_off;
-# if defined(VGA_x86) || defined(VGA_amd64)
+# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
si->cfa_how = CFIC_IA_SPREL;
# elif defined(VGA_arm)
si->cfa_how = CFIC_ARM_R13REL;
else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
si->cfa_off = ctxs->cfa_off;
-# if defined(VGA_x86) || defined(VGA_amd64)
+# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
si->cfa_how = CFIC_IA_BPREL;
# elif defined(VGA_arm)
si->cfa_how = CFIC_ARM_R12REL;
si->cfa_how = CFIC_ARM_R11REL;
si->cfa_off = ctxs->cfa_off;
}
+ else
+ if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 7/*??_REG*/) {
+ si->cfa_how = CFIC_ARM_R7REL;
+ si->cfa_off = ctxs->cfa_off;
+ }
# endif
else {
why = 1;
SUMMARISE_HOW(si->r11_how, si->r11_off,
ctxs->reg[11/*FP_REG*/] );
+ SUMMARISE_HOW(si->r7_how, si->r7_off,
+ ctxs->reg[7] );
+
if (ctxs->reg[14/*LR*/].tag == RR_Same
&& ctx->ra_reg == 14/*as we expect it always to be*/) {
/* Generate a trivial CfiExpr, which merely says "r14". First
return True;
+# elif defined(VGA_s390x)
+
+ SUMMARISE_HOW(si->ra_how, si->ra_off,
+ ctxs->reg[ctx->ra_reg] );
+ SUMMARISE_HOW(si->fp_how, si->fp_off,
+ ctxs->reg[FP_REG] );
+ SUMMARISE_HOW(si->sp_how, si->sp_off,
+ ctxs->reg[SP_REG] );
+
+ /* change some defaults to consumable values */
+ if (si->sp_how == CFIR_UNKNOWN)
+ si->sp_how = CFIR_SAME;
+
+ if (si->fp_how == CFIR_UNKNOWN)
+ si->fp_how = CFIR_SAME;
+
+ if (si->cfa_how == CFIR_UNKNOWN) {
+ si->cfa_how = CFIC_IA_SPREL;
+ si->cfa_off = 160;
+ }
+ if (si->ra_how == CFIR_UNKNOWN) {
+ if (!debuginfo->cfsi_exprs)
+ debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
+ "di.ccCt.2a",
+ ML_(dinfo_free),
+ sizeof(CfiExpr) );
+ si->ra_how = CFIR_EXPR;
+ si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
+ Creg_S390_R14);
+ }
+
+ /* knock out some obviously stupid cases */
+ if (si->ra_how == CFIR_SAME)
+ { why = 3; goto failed; }
+
+ /* bogus looking range? Note, we require that the difference is
+ representable in 32 bits. */
+ if (loc_start >= ctx->loc)
+ { why = 4; goto failed; }
+ if (ctx->loc - loc_start > 10000000 /* let's say */)
+ { why = 5; goto failed; }
+
+ si->base = loc_start + ctx->initloc;
+ si->len = (UInt)(ctx->loc - loc_start);
+
+ return True;
+
+
+
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"
Int srcix )
{
CfiExpr* src;
- Int cpL, cpR, cpA, dwreg;
+ Int cpL, cpR, cpA;
XArray* srcxa = srcuc->exprs;
vg_assert(srcxa);
vg_assert(dstxa);
/* should not see these in input (are created only by this
conversion step!) */
VG_(core_panic)("copy_convert_CfiExpr_tree: CfiReg in input");
- case Cex_DwReg:
+ case Cex_DwReg: {
/* This is the only place where the conversion can fail. */
+ Int dwreg __attribute__((unused));
dwreg = src->Cex.DwReg.reg;
# if defined(VGA_x86) || defined(VGA_amd64)
if (dwreg == SP_REG)
return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R12 );
if (dwreg == srcuc->ra_reg)
return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R15 ); /* correct? */
+# elif defined(VGA_s390x)
+ if (dwreg == SP_REG)
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
+ if (dwreg == FP_REG)
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
+ if (dwreg == srcuc->ra_reg)
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"
# endif
/* else we must fail - can't represent the reg */
return -1;
+ }
default:
VG_(core_panic)("copy_convert_CfiExpr_tree: default");
}
static Short read_Short ( UChar* data )
{
Short r = 0;
- vg_assert(host_is_little_endian());
- r = data[0]
- | ( ((UInt)data[1]) << 8 );
+ if (host_is_little_endian()) {
+ r = data[0]
+ | ( ((UInt)data[1]) << 8 );
+ } else {
+ r = data[1]
+ | ( ((UInt)data[0]) << 8 );
+ }
return r;
}
static Int read_Int ( UChar* data )
{
Int r = 0;
- vg_assert(host_is_little_endian());
- r = data[0]
- | ( ((UInt)data[1]) << 8 )
- | ( ((UInt)data[2]) << 16 )
- | ( ((UInt)data[3]) << 24 );
+ if (host_is_little_endian()) {
+ r = data[0]
+ | ( ((UInt)data[1]) << 8 )
+ | ( ((UInt)data[2]) << 16 )
+ | ( ((UInt)data[3]) << 24 );
+ } else {
+ r = data[3]
+ | ( ((UInt)data[2]) << 8 )
+ | ( ((UInt)data[1]) << 16 )
+ | ( ((UInt)data[0]) << 24 );
+ }
return r;
}
static Long read_Long ( UChar* data )
{
Long r = 0;
- vg_assert(host_is_little_endian());
- r = data[0]
- | ( ((ULong)data[1]) << 8 )
- | ( ((ULong)data[2]) << 16 )
- | ( ((ULong)data[3]) << 24 )
- | ( ((ULong)data[4]) << 32 )
- | ( ((ULong)data[5]) << 40 )
- | ( ((ULong)data[6]) << 48 )
- | ( ((ULong)data[7]) << 56 );
+ if (host_is_little_endian()) {
+ r = data[0]
+ | ( ((ULong)data[1]) << 8 )
+ | ( ((ULong)data[2]) << 16 )
+ | ( ((ULong)data[3]) << 24 )
+ | ( ((ULong)data[4]) << 32 )
+ | ( ((ULong)data[5]) << 40 )
+ | ( ((ULong)data[6]) << 48 )
+ | ( ((ULong)data[7]) << 56 );
+ } else {
+ r = data[7]
+ | ( ((ULong)data[6]) << 8 )
+ | ( ((ULong)data[5]) << 16 )
+ | ( ((ULong)data[4]) << 24 )
+ | ( ((ULong)data[3]) << 32 )
+ | ( ((ULong)data[2]) << 40 )
+ | ( ((ULong)data[1]) << 48 )
+ | ( ((ULong)data[0]) << 56 );
+ }
return r;
}
static UShort read_UShort ( UChar* data )
{
UInt r = 0;
- vg_assert(host_is_little_endian());
- r = data[0]
- | ( ((UInt)data[1]) << 8 );
+ if (host_is_little_endian()) {
+ r = data[0]
+ | ( ((UInt)data[1]) << 8 );
+ } else {
+ r = data[1]
+ | ( ((UInt)data[0]) << 8 );
+ }
return r;
}
static UInt read_UInt ( UChar* data )
{
UInt r = 0;
- vg_assert(host_is_little_endian());
- r = data[0]
- | ( ((UInt)data[1]) << 8 )
- | ( ((UInt)data[2]) << 16 )
- | ( ((UInt)data[3]) << 24 );
+ if (host_is_little_endian()) {
+ r = data[0]
+ | ( ((UInt)data[1]) << 8 )
+ | ( ((UInt)data[2]) << 16 )
+ | ( ((UInt)data[3]) << 24 );
+ } else {
+ r = data[3]
+ | ( ((UInt)data[2]) << 8 )
+ | ( ((UInt)data[1]) << 16 )
+ | ( ((UInt)data[0]) << 24 );
+ }
return r;
}
static ULong read_ULong ( UChar* data )
{
ULong r = 0;
- vg_assert(host_is_little_endian());
- r = data[0]
- | ( ((ULong)data[1]) << 8 )
- | ( ((ULong)data[2]) << 16 )
+ if (host_is_little_endian()) {
+ r = data[0]
+ | ( ((ULong)data[1]) << 8 )
+ | ( ((ULong)data[2]) << 16 )
| ( ((ULong)data[3]) << 24 )
- | ( ((ULong)data[4]) << 32 )
- | ( ((ULong)data[5]) << 40 )
- | ( ((ULong)data[6]) << 48 )
+ | ( ((ULong)data[4]) << 32 )
+ | ( ((ULong)data[5]) << 40 )
+ | ( ((ULong)data[6]) << 48 )
| ( ((ULong)data[7]) << 56 );
+ } else {
+ r = data[7]
+ | ( ((ULong)data[6]) << 8 )
+ | ( ((ULong)data[5]) << 16 )
+ | ( ((ULong)data[4]) << 24 )
+ | ( ((ULong)data[3]) << 32 )
+ | ( ((ULong)data[2]) << 40 )
+ | ( ((ULong)data[1]) << 48 )
+ | ( ((ULong)data[0]) << 56 );
+ }
return r;
}
ctxs = &ctx->state[ctx->state_sp];
if (hi2 == DW_CFA_advance_loc) {
delta = (UInt)lo6;
+ delta *= ctx->code_a_f;
ctx->loc += delta;
if (di->ddump_frames)
VG_(printf)(" DW_CFA_advance_loc: %d to %08lx\n",
break;
case DW_CFA_advance_loc1:
delta = (UInt)read_UChar(&instr[i]); i+= sizeof(UChar);
+ delta *= ctx->code_a_f;
ctx->loc += delta;
if (di->ddump_frames)
VG_(printf)(" DW_CFA_advance_loc1: %d to %08lx\n",
break;
case DW_CFA_advance_loc2:
delta = (UInt)read_UShort(&instr[i]); i+= sizeof(UShort);
+ delta *= ctx->code_a_f;
ctx->loc += delta;
if (di->ddump_frames)
VG_(printf)(" DW_CFA_advance_loc2: %d to %08lx\n",
break;
case DW_CFA_advance_loc4:
delta = (UInt)read_UInt(&instr[i]); i+= sizeof(UInt);
+ delta *= ctx->code_a_f;
ctx->loc += delta;
if (di->ddump_frames)
VG_(printf)(" DW_CFA_advance_loc4: %d to %08lx\n",
ctxs->cfa_reg = reg;
/* ->cfa_off unchanged */
if (di->ddump_frames)
- VG_(printf)(" DW_CFA_def_cfa_reg: r%d\n", (Int)reg );
+ VG_(printf)(" DW_CFA_def_cfa_register: r%d\n", (Int)reg );
break;
case DW_CFA_def_cfa_offset: