symbol *except_gentables() { //printf("except_gentables()\n"); if (config.ehmethod == EH_DM) { // BUG: alloca() changes the stack size, which is not reflected // in the fixed eh tables. if (Alloca.size) error(NULL, 0, 0, "cannot mix core.std.stdlib.alloca() and exception handling in %s()", funcsym_p->Sident); char name[13+5+1]; static int tmpnum; sprintf(name,"_HandlerTable%d",tmpnum++); symbol *s = symbol_name(name,SCstatic,tsint); symbol_keep(s); symbol_debug(s); except_fillInEHTable(s); outdata(s); // output the scope table objmod->ehtables(funcsym_p,funcsym_p->Ssize,s); } return NULL; }
void win64_pdata(Symbol *sf) { // return; // doesn't work yet //printf("win64_pdata()\n"); assert(config.exe == EX_WIN64); // Generate the pdata name, which is $pdata$funcname size_t sflen = strlen(sf->Sident); char *pdata_name = (char *)alloca(7 + sflen + 1); assert(pdata_name); memcpy(pdata_name, "$pdata$", 7); memcpy(pdata_name + 7, sf->Sident, sflen + 1); // include terminating 0 symbol *spdata = symbol_name(pdata_name,SCstatic,tsint); symbol_keep(spdata); symbol_debug(spdata); symbol *sunwind = win64_unwind(sf); /* 3 pointers are emitted: * 1. pointer to start of function sf * 2. pointer past end of function sf * 3. pointer to unwind data */ dt_t **pdt = &spdata->Sdt; pdt = dtxoff(pdt,sf,0,TYint); // Note the TYint, these are 32 bit fixups pdt = dtxoff(pdt,sf,retoffset + retsize,TYint); pdt = dtxoff(pdt,sunwind,0,TYint); spdata->Sseg = symbol_iscomdat(sf) ? MsCoffObj::seg_pdata_comdat(sf) : MsCoffObj::seg_pdata(); spdata->Salignment = 4; outdata(spdata); }
symbol *except_gentables() { //printf("except_gentables()\n"); if (OUREH) { // BUG: alloca() changes the stack size, which is not reflected // in the fixed eh tables. assert(!usedalloca); char name[13+5+1]; static int tmpnum; sprintf(name,"_HandlerTable%d",tmpnum++); symbol *s = symbol_name(name,SCstatic,tsint); symbol_keep(s); symbol_debug(s); except_fillInEHTable(s); outdata(s); // output the scope table objmod->ehtables(funcsym_p,funcsym_p->Ssize,s); } return NULL; }
symbol *symboldata(targ_size_t offset,tym_t ty) { symbol *s = symbol_generate(SClocstat, type_fake(ty)); s->Sfl = FLdata; s->Soffset = offset; symbol_keep(s); // keep around return s; }
STATIC symbol *nteh_scopetable() { symbol *s; type *t; if (!s_table) { t = type_alloc(TYint); s = symbol_generate(SCstatic,t); s->Sseg = UNKNOWN; symbol_keep(s); s_table = s; } return s_table; }
Symbol *win64_unwind(Symbol *sf) { // Generate the unwind name, which is $unwind$funcname size_t sflen = strlen(sf->Sident); char *unwind_name = (char *)alloca(8 + sflen + 1); assert(unwind_name); memcpy(unwind_name, "$unwind$", 8); memcpy(unwind_name + 8, sf->Sident, sflen + 1); // include terminating 0 symbol *sunwind = symbol_name(unwind_name,SCstatic,tsint); symbol_keep(sunwind); symbol_debug(sunwind); sunwind->Sdt = unwind_data(); sunwind->Sseg = symbol_iscomdat(sf) ? MsCoffObj::seg_xdata_comdat(sf) : MsCoffObj::seg_xdata(); sunwind->Salignment = 1; outdata(sunwind); return sunwind; }
symbol *except_gentables() { //printf("except_gentables()\n"); #if OUREH // BUG: alloca() changes the stack size, which is not reflected // in the fixed eh tables. assert(!usedalloca); symbol *s = symbol_generate(SCstatic,tsint); s->Sseg = UNKNOWN; symbol_keep(s); symbol_debug(s); except_fillInEHTable(s); outdata(s); // output the scope table obj_ehtables(funcsym_p,funcsym_p->Ssize,s); #endif return NULL; }
symbol *except_gentables() { //printf("except_gentables()\n"); #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS symbol *s; int sz; // size so far dt_t **pdt; unsigned fsize; // target size of function pointer long spoff; block *b; int guarddim; int i; // BUG: alloca() changes the stack size, which is not reflected // in the fixed eh tables. assert(!usedalloca); s = symbol_generate(SCstatic,tsint); s->Sseg = UNKNOWN; symbol_keep(s); symbol_debug(s); fsize = 4; pdt = &s->Sdt; sz = 0; /* void* pointer to start of function unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] { unsigned offset; // offset of start of guarded section unsigned endoffset; // ending offset of guarded section int last_index; // previous index (enclosing guarded section) unsigned catchoffset; // offset to catch block from symbol void *finally; // finally code to execute } guard[]; catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ #define GUARD_SIZE 5 // number of 4 byte values in one guard sz = 0; // Address of start of function symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset guarddim = 0; // max dimension of guard[] for (b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); } pdt = dtdword(pdt,guarddim); sz += 4; unsigned catchoffset = sz + guarddim * (GUARD_SIZE * 4); // Generate guard[] i = 0; for (b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { dt_t *dt; block *bhandler; int nsucc; unsigned endoffset; block *bn; assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * (GUARD_SIZE * 4); pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; nsucc = list_nitems(b->Bsucc); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset for (bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } pdt = dtdword(pdt,endoffset); // offset past end of guarded block pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { pdt = dtdword(pdt,catchoffset); pdt = dtdword(pdt,0); // no finally handler catchoffset += 4 + (nsucc - 1) * (3 * 4); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr); // finally handler address //pdt = dtcoff(pdt,bhandler->Boffset); // finally handler address } sz += GUARD_SIZE + 4; } } // Generate catch[] for (b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { block *bhandler; int nsucc; if (b->jcatchvar) // if try-catch { list_t bl; nsucc = list_nitems(b->Bsucc); pdt = dtdword(pdt,nsucc - 1); // # of catch blocks sz += 4; for (bl = list_next(b->Bsucc); bl; bl = list_next(bl)) { block *bcatch = list_block(bl); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle); pdt = dtdword(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr); // catch handler address //pdt = dtcoff(pdt,bcatch->Boffset); // catch handler address sz += 3 * 4; } } } } assert(sz != 0); outdata(s); // output the scope table obj_ehtables(funcsym_p,funcsym_p->Ssize,s); #endif return NULL; }