Skip to content

Commit

Permalink
Dwarf EH: more fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Dec 27, 2015
1 parent 6cd7173 commit 51666e0
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 18 deletions.
2 changes: 2 additions & 0 deletions src/backend/cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,8 @@ typedef struct FUNC_S
Symbol **typesTable;
size_t typesTableDim; // number used in typesTable[]
size_t typesTableCapacity; // allocated capacity of typesTable[]

unsigned LSDAoffset; // offset in LSDA segment of the LSDA data for this function
} func_t;

#define func_calloc() ((func_t *) mem_fcalloc(sizeof(func_t)))
Expand Down
2 changes: 1 addition & 1 deletion src/backend/cod2.c
Original file line number Diff line number Diff line change
Expand Up @@ -5122,7 +5122,7 @@ code *cdddtor(elem *e,regm_t *pretregs)

assert(*pretregs == 0);
code *c = codelem(e->E1,pretregs,FALSE);
return c;
return cat(cd, c);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/backend/cod3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3003,7 +3003,7 @@ code* prolog_frame(unsigned farfunc, unsigned* xlocalsize, bool* enter)
dwarf_CFA_set_loc(1); // address after PUSH EBP
dwarf_CFA_set_reg_offset(SP, off); // CFA is now 8[ESP]
dwarf_CFA_offset(BP, -off); // EBP is at 0[ESP]
dwarf_CFA_set_loc(3); // address after MOV EBP,ESP
dwarf_CFA_set_loc(I64 ? 4 : 3); // address after MOV EBP,ESP
// Yes, I know the parameter is 8 when we mean 0!
// But this gets the cfa register set to EBP correctly
dwarf_CFA_set_reg_offset(BP, off); // CFA is now 0[EBP]
Expand Down
40 changes: 30 additions & 10 deletions src/backend/dwarf.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ int dwarf_getsegment(const char *name, int align)
#endif
}

int dwarf_getsegment_alloc(const char *name, int align)
{
#if ELFOBJ
return ElfObj::getsegment(name, NULL, SHT_PROGBITS, SHF_ALLOC, align * 4);
#elif MACHOBJ
return MachObj::getsegment(name, "__DWARF", align * 2, S_ATTR_DEBUG);
#else
assert(0);
return 0;
#endif
}

// machobj.c
#define RELaddr 0 // straight address
#define RELrel 1 // relative to location to be fixed up
Expand Down Expand Up @@ -626,13 +638,14 @@ static void writeEhFrameHeader(IDXSEC dfseg, Outbuffer *buf, Symbol *personality
buf->writeByten(DW_EH_PE_pcrel | DW_EH_PE_sdata4); // R: encoding of addresses in FDE
}

// Set CFA beginning state at function entry point
if (I64)
{
buf->writeByten(DW_CFA_def_cfa); // DEF_CFA r7,8
buf->writeByten(DW_CFA_def_cfa); // DEF_CFA r7,8 RSP is at offset 8
buf->writeByten(7);
buf->writeByten(8);

buf->writeByten(DW_CFA_offset + 16); // OFFSET r16,1
buf->writeByten(DW_CFA_offset + 16); // OFFSET r16,1 RIP is at -8*1[RSP]
buf->writeByten(1);
}
else
Expand Down Expand Up @@ -757,17 +770,23 @@ void writeEhFrameFDE(IDXSEC dfseg, Symbol *sfunc)
const unsigned pad = -fdelen & (I64 ? 7 : 3); // pad to addressing unit size boundary
const unsigned length = fdelen + pad - 4;

buf->reserve(length + 4);
buf->write32(length); // Length (no Extended Length)
buf->write32((startsize + 4) - CIE_offset); // CIE Pointer
ElfObj::reftoident(dfseg, startsize + 8, sfunc, 0, CFpc32 | CFoff); // PC_begin
#if ELFOBJ
buf->write32(0); // address of function
ElfObj::addrel(dfseg, startsize + 8, R_X86_64_PC32, MAP_SEG2SYMIDX(sfunc->Sseg), sfunc->Soffset);
//ElfObj::reftoident(dfseg, startsize + 8, sfunc, 0, CFpc32 | CFoff); // PC_begin
#else
assert(0); // not supported yet
#endif
buf->write32(sfunc->Ssize); // PC Range
if (config.ehmethod == EH_DWARF)
{
buf->writeByten(4); // Augmentation Data Length
int etseg = dwarf_getsegment(except_table_name, 1);
Outbuffer *etbuf = SegData[etseg]->SDbuf;
int etseg = dwarf_getsegment_alloc(except_table_name, 1);
buf->write32(0); // address of LSDA (".gcc_except_table")
dwarf_addrel(dfseg, buf->size() - 4, etseg, etbuf->size()); // and the fixup
dwarf_addrel(dfseg, buf->size() - 4, etseg, sfunc->Sfunc->LSDAoffset); // and the fixup
}
else
buf->writeByten(0); // Augmentation Data Length
Expand All @@ -784,9 +803,9 @@ void dwarf_initfile(const char *filename)
{
if (config.ehmethod == EH_DWARF)
{
dwarf_getsegment(except_table_name, 1);
dwarf_getsegment_alloc(except_table_name, 1);

int seg = dwarf_getsegment(eh_frame_name, 1);
int seg = dwarf_getsegment_alloc(eh_frame_name, I64 ? 2 : 1);
Outbuffer *buf = SegData[seg]->SDbuf;
buf->reserve(1000);
writeEhFrameHeader(seg, buf, getRtlsym(RTLSYM_PERSONALITY));
Expand Down Expand Up @@ -1269,7 +1288,7 @@ void dwarf_func_term(Symbol *sfunc)

if (config.ehmethod == EH_DWARF)
{
IDXSEC dfseg = dwarf_getsegment(eh_frame_name, 1);
IDXSEC dfseg = dwarf_getsegment_alloc(eh_frame_name, I64 ? 2 : 1);
writeEhFrameFDE(dfseg, sfunc);
}
if (!config.fulltypes)
Expand Down Expand Up @@ -2690,9 +2709,10 @@ unsigned dwarf_abbrev_code(unsigned char *data, size_t nbytes)
*/
void dwarf_except_gentables(Funcsym *sfunc, unsigned startoffset, unsigned retoffset)
{
int seg = dwarf_getsegment(except_table_name, 1);
int seg = dwarf_getsegment_alloc(except_table_name, 1);
Outbuffer *buf = SegData[seg]->SDbuf;
buf->reserve(100);
sfunc->Sfunc->LSDAoffset = buf->size();
genDwarfEh(sfunc, seg, buf, usednteh & EHcleanup, startoffset, retoffset);
}

Expand Down
41 changes: 38 additions & 3 deletions src/backend/dwarfeh.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct DwEhTable

DwEhTableEntry *index(unsigned i)
{
if (i >= dim) printf("i = %d dim = %d\n", i, dim);
assert(i < dim);
return ptr + i;
}
Expand All @@ -70,7 +71,7 @@ struct DwEhTable
ptr = (DwEhTableEntry *)::realloc(ptr, capacity * sizeof(DwEhTableEntry));
assert(ptr);
}
memset(ptr + dim, 0, sizeof(DwEhTable));
memset(ptr + dim, 0, sizeof(DwEhTableEntry));
return dim++;
}
};
Expand Down Expand Up @@ -114,12 +115,19 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
et->reserve(100);
block *startblock = sfunc->Sfunc->Fstartblock;
//printf("genDwarfEh: func = %s, offset = x%x, startblock->Boffset = x%x, scancode = %d\n",
// sfunc->Sident, (int)sfunc->Soffset, (int)startblock->Boffset, scancode);
//sfunc->Sident, (int)sfunc->Soffset, (int)startblock->Boffset, scancode);

#if 0
printf("------- before ----------\n");
for (block *b = startblock; b; b = b->Bnext) WRblock(b);
printf("-------------------------\n");
#endif

unsigned startsize = et->size();
assert((startsize & 3) == 0); // should be aligned

DwEhTable *deh = &dwehtable;
deh->dim = 0;
Outbuffer atbuf;
Outbuffer cstbuf;

Expand Down Expand Up @@ -153,9 +161,9 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
d->start = b->Boffset;

block *bf = b->nthSucc(1);
d->lpad = bf->Boffset;
if (bf->BC == BCjcatch)
{
d->lpad = bf->Boffset;
d->bcatch = bf;
unsigned *pat = bf->BS.BIJCATCH.actionTable;
unsigned length = pat[0];
Expand All @@ -170,6 +178,8 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
}
d->action = offset + 1;
}
else
d->lpad = bf->nthSucc(0)->Boffset;
d->prev = index;
index = i;
bprev = b->Btry;
Expand Down Expand Up @@ -206,6 +216,30 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
}
//printf("deh->dim = %d\n", (int)deh->dim);

#if 1
/* Build Call Site Table
* Be sure to not generate empty entries,
* and generate nested ranges reflecting the layout in the code.
*/
assert(deh->dim);
unsigned end = deh->index(0)->start;
for (unsigned i = 0; i < deh->dim; ++i)
{
DwEhTableEntry *d = deh->index(i);
if (d->start < d->end)
{
unsigned CallSiteStart = d->start - startblock->Boffset;
cstbuf.writeuLEB128(CallSiteStart);
unsigned CallSiteRange = d->end - d->start;
cstbuf.writeuLEB128(CallSiteRange);
unsigned LandingPad = d->lpad - startblock->Boffset;
cstbuf.writeuLEB128(LandingPad);
unsigned ActionTable = d->action;
cstbuf.writeuLEB128(ActionTable);
//printf("\t%x %x %x %x\n", CallSiteStart, CallSiteRange, LandingPad, ActionTable);
}
}
#else
/* Build Call Site Table
* Be sure to not generate empty entries,
* and generate multiple entries for one DwEhTableEntry if the latter
Expand Down Expand Up @@ -250,6 +284,7 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
}
} while (j--);
}
#endif

/* Write LSDT header */
const unsigned char LPstart = DW_EH_PE_omit;
Expand Down
1 change: 1 addition & 0 deletions src/backend/rtlsym.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ SYMBOL_MARS(D_LOCAL_UNWIND2, FLfunc,FREGSAVED,"_d_local_unwind2", 0, tsclib) \
SYMBOL_SCPP(LOCAL_UNWIND2, FLfunc,FREGSAVED,"_local_unwind2", 0, tsclib) \
SYMBOL_Z(UNWIND_RESUME, FLfunc,FREGSAVED,"_Unwind_Resume", SFLexit, tsclib) \
SYMBOL_Z(PERSONALITY, FLfunc,FREGSAVED,"__dmd_personality_v0", 0, tsclib) \
SYMBOL_Z(BEGIN_CATCH, FLfunc,FREGSAVED,"__dmd_begin_catch", 0, tsclib) \
\
SYMBOL_Z(TLS_INDEX, FLextern,0,"_tls_index",0,tsint) \
SYMBOL_Z(TLS_ARRAY, FLextern,0,"_tls_array",0,tspvoid) \
Expand Down
15 changes: 12 additions & 3 deletions src/s2ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,8 @@ class S2irVisitor : public Visitor

incUsage(irs, s->loc);
elem *e = toElemDtor(s->exp, irs);
e = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_THROWC)),e);
const int rtlthrow = config.ehmethod == EH_DWARF ? RTLSYM_THROWDWARF : RTLSYM_THROWC;
e = el_bin(OPcall, TYvoid, el_var(getRtlsym(rtlthrow)),e);
block_appendexp(blx->curblock, e);
}

Expand Down Expand Up @@ -1033,7 +1034,8 @@ class S2irVisitor : public Visitor
* BCjcatch:
* __hander = __RDX;
* __exception_object = __RAX;
* jcatchvar = *(__exception_object - Target::ptrsize)
* jcatchvar = *(__exception_object - Target::ptrsize); // old way
* jcatchvar = __dmd_catch_begin(__exception_object); // new way
* switch (__handler)
* case 1: // first catch handler
* *(sclosure + cs.var.offset) = cs.var;
Expand All @@ -1058,12 +1060,18 @@ class S2irVisitor : public Visitor
elem *e1 = el_bin(OPeq, TYvoid, el_var(shandler), el_var(sedx)); // __handler = __RDX
elem *e2 = el_bin(OPeq, TYvoid, el_var(seo), el_var(seax)); // __exception_object = __RAX

#if 0
// jcatchvar = *(__exception_object - Target::ptrsize)
union eve c;
memset(&c, 0, sizeof(c));
c.Vllong = Target::ptrsize;
elem *e = el_bin(OPmin, TYptr, el_var(seo), el_const(TYsize_t, &c));
elem *e = el_bin(OPmin, TYnptr, el_var(seo), el_const(TYsize_t, &c));
elem *e3 = el_bin(OPeq, TYvoid, el_var(tryblock->jcatchvar), el_una(OPind, TYnptr, e));
#else
// jcatchvar = __dmd_catch_begin(__exception_object);
elem *e = el_bin(OPcall, TYnptr, el_var(getRtlsym(RTLSYM_BEGIN_CATCH)), el_var(seo));
elem *e3 = el_bin(OPeq, TYvoid, el_var(tryblock->jcatchvar), e);
#endif

block *bcatch = blx->curblock;
tryblock->appendSucc(bcatch);
Expand Down Expand Up @@ -1572,6 +1580,7 @@ void insertFinallyBlockCalls(block *startblock)
eeq->ET = e->ET;
eeq->E1->ET = e->ET;
}
b->Belem = eeq;

goto case_goto;
}
Expand Down

0 comments on commit 51666e0

Please sign in to comment.