void timed_test(F func, int secs, execution_monitor::wait_type type = execution_monitor::use_sleep_only) { execution_monitor monitor(type, secs); indirect_adapter<F> ifunc(func, monitor); monitor.start(); boost::thread thrd(ifunc); BOOST_REQUIRE(monitor.wait()); // Timed test didn't complete in time, possible deadlock }
/*==========================================+ * evaluate_func -- Evaluate builtin function *=========================================*/ PVALUE evaluate_func (PNODE node, SYMTAB stab, BOOLEAN *eflg) { PVALUE val; *eflg = FALSE; if (prog_trace) trace_outl("evaluate_func called: %d: %s", iline(node)+1, iname(node)); val = (*(PFUNC)ifunc(node))(node, stab, eflg); return val; }
int edview_search_tag_type(edview *xx, int dir, int strand, char *value) { contig_iterator *iter; int start, end; rangec_t *r; rangec_t *(*ifunc)(GapIO *io, contig_iterator *ci); int type = str2type(value); contig_t *c = cache_search(xx->io, GT_Contig, xx->cnum); if (dir) { start = xx->cursor_apos + (dir ? 1 : -1); end = c->end; ifunc = contig_iter_next; } else { start = c->start; end = xx->cursor_apos + (dir ? 1 : -1); ifunc = contig_iter_prev; } iter = contig_iter_new_by_type(xx->io, xx->cnum, 1, dir == 1 ? CITER_FIRST : CITER_LAST, start, end, GRANGE_FLAG_ISANNO); if (!iter) /* Can happen legitimately when we're already at the end of contig */ return -1; while (r = ifunc(xx->io, iter)) { if ((dir && r->start < start) || (!dir && r->start > end)) continue; if (r->mqual == type) break; } if (r) { if (r->flags & GRANGE_FLAG_TAG_SEQ) { int pos; sequence_get_position(xx->io, r->pair_rec, NULL, &pos, NULL, NULL); pos = r->start - pos; edSetCursorPos(xx, GT_Seq, r->pair_rec, pos, 1); } else { edSetCursorPos(xx, GT_Contig, xx->cnum, r->start, 1); } contig_iter_del(iter); return 0; } contig_iter_del(iter); return -1; }
int edview_search_tag_indel(edview *xx, int dir, int strand, char *value) { contig_iterator *iter; int start, end; rangec_t *r; rangec_t *(*ifunc)(GapIO *io, contig_iterator *ci); contig_t *c = cache_search(xx->io, GT_Contig, xx->cnum); if (dir) { start = xx->cursor_apos + (dir ? 1 : -1); end = c->end; ifunc = contig_iter_next; } else { start = c->start; end = xx->cursor_apos + (dir ? 1 : -1); ifunc = contig_iter_prev; } iter = contig_iter_new_by_type(xx->io, xx->cnum, 1, dir == 1 ? CITER_FIRST : CITER_LAST, start, end, GRANGE_FLAG_ISREFPOS); if (!iter) return -1; while (r = ifunc(xx->io, iter)) { if ((dir && r->start < start) || (!dir && r->start > end)) continue; break; } if (r) { edSetCursorPos(xx, GT_Contig, xx->cnum, r->start, 1); contig_iter_del(iter); return 0; } contig_iter_del(iter); return -1; }
int edview_search_name(edview *xx, int dir, int strand, char *value) { tg_rec rec, *rp, cnum = -1, best_rec; int best_pos, best_off; int nr, i; rangec_t *(*ifunc)(GapIO *io, contig_iterator *ci); int start, end, cstart; contig_iterator *iter; contig_t *c; /* Check for #num where num is a sequence record in this contig */ if (*value == '#') { char *endp; int64_t v = strtol64(value+1, &endp, 10); rec = v; if (*endp == '\0' && cache_exists(xx->io, GT_Seq, rec)) { sequence_get_clipped_position(xx->io, rec, &cnum, &start, NULL, &cstart, NULL, NULL); if (cnum == xx->cnum) { edSetCursorPos(xx, GT_Seq, rec, cstart - start, 1); return 0; } } } /* Find all hits matching this name */ rp = sequence_index_query_all(xx->io, value, 1, &nr); /* Also get an position-based iterator */ c = cache_search(xx->io, GT_Contig, xx->cnum); if (dir) { start = xx->cursor_apos + 1; end = c->end; ifunc = contig_iter_next; best_pos = end + 1; best_off = 0; } else { start = c->start; end = xx->cursor_apos - 1; ifunc = contig_iter_prev; best_pos = start - 1; best_off = 0; } iter = contig_iter_new_by_type(xx->io, xx->cnum, 1, dir == 1 ? CITER_FIRST : CITER_LAST, start-1, end+1, GRANGE_FLAG_ISSEQ); if (!iter) return -1; /* * The iterator also finds overlapping objects, not just ones beyond this * point. That's fine if we're on the consensus as we probably want to * jump to the first seq-name overlapping this point. * * However if we're on a sequence already, we want the first one * after or before that sequence. So we skip along iterator until we're * at the current record. */ if (xx->cursor_type == GT_Seq) { rangec_t *r; while ((r = ifunc(xx->io, iter))) { if (r->rec == xx->cursor_rec) break; } } /* Alternate between the by-name and by-position scan */ best_rec = -1; for (i = 0; i < nr; i++) { int start, end; rangec_t *r; /* From name index */ rec = rp[i++]; sequence_get_clipped_position(xx->io, rec, &cnum, &start, &end, &cstart, NULL, NULL); if (cnum == xx->cnum) { if ((dir && best_pos > cstart && cstart > xx->cursor_apos) || (!dir && best_pos < cstart && cstart < xx->cursor_apos)) { best_pos = cstart; best_off = cstart - start; best_rec = rec; } } /* From iterator */ if ((r = ifunc(xx->io, iter))) { seq_t *s; if (NULL == (s = cache_search(xx->io, GT_Seq, r->rec))) { /* No match */ best_rec = -1; break; } if (strncmp(s->name, value, strlen(value)) == 0) { /* prefix match */ puts("Found by pos iterator"); best_rec = r->rec; break; } } else { /* End of contig - bail out early */ best_rec = -1; break; } } contig_iter_del(iter); if (rp) free(rp); if (best_rec != -1) { edSetCursorPos(xx, GT_Seq, best_rec, best_off, 1); return 0; } return -1; }
int edview_search_sequence(edview *xx, int dir, int strand, char *value) { int mismatches = 0; /* exact match */ int where = 2; /* consensus */ char *p; int start, end; int patlen; char *uppert, *upperb; int found = 0, at_end = 0; tg_rec fseq; int fpos, i, j; contig_t *c; contig_iterator *iter; rangec_t *(*ifunc)(GapIO *io, contig_iterator *ci); rangec_t *r; int best_pos; if (dir) { start = xx->cursor_apos + 1; end = CITER_CEND; iter = contig_iter_new(xx->io, xx->cnum, 1, CITER_FIRST | CITER_ISTART, start, end); ifunc = contig_iter_next; best_pos = INT_MAX; } else { start = CITER_CSTART; end = xx->cursor_apos -1; iter = contig_iter_new(xx->io, xx->cnum, 1, CITER_LAST | CITER_IEND, start, end); ifunc = contig_iter_prev; best_pos = INT_MIN; } if (!iter) return -1; /* * Parse value search string. It optionally includes two extra params * separated by #. Ie: * <string>#<N.mismatches>#<where>. * <where> is 1 for readings, 2 for consensus, 3 for both. */ if (p = strchr(value, '#')) { mismatches = atoi(p+1); *p = 0; if (p = strchr(p+1, '#')) where = atoi(p+1); } /* uppercase search string, remove pads, and store fwd/rev copies */ patlen = strlen(value); depad_seq(value, &patlen, NULL); if (NULL == (uppert = (char *)xmalloc(patlen + 1))) return 0; if (NULL == (upperb = (char *)xmalloc(patlen + 1))) return 0; uppert[patlen] = upperb[patlen] = 0; for (i = patlen-1; i >= 0; i--) { upperb[i] = uppert[i] = toupper(value[i]); } complement_seq(upperb, patlen); while ((r = ifunc(xx->io, iter))) { seq_t *s, *sorig; char *ind, *indt = NULL, *indb = NULL, *seq; int seq_len, comp, off = 0; if (found && dir && r->start > best_pos) break; if (found && !dir && r->end < best_pos) break; if (NULL == (s = sorig = cache_search(xx->io, GT_Seq, r->rec))) break; if (r->comp ^ (s->len < 0)) { s = dup_seq(s); complement_seq_t(s); } seq = s->seq; seq_len = ABS(s->len); if (r->start < start) { off = start - r->start; seq += off; seq_len -= off; } if (r->end - (patlen-1) > end) seq_len -= r->end - (patlen-1) - end; if (dir) { if (strand == '+' || strand == '=') indt = pstrnstr_inexact(seq, seq_len, uppert, patlen, mismatches, NULL); if (strand == '-' || strand == '=') indb = pstrnstr_inexact(seq, seq_len, upperb, patlen, mismatches, NULL); } else { if (strand == '+' || strand == '=') indt = prstrnstr_inexact(seq, seq_len, uppert, patlen, mismatches, NULL); if (strand == '-' || strand == '=') indb = prstrnstr_inexact(seq, seq_len, upperb, patlen, mismatches, NULL); } if (indt && indb) ind = MIN(indt, indb); else if (indt) ind = indt; else if (indb) ind = indb; else ind = NULL; if (ind) { int pos = r->start + ind - seq + off; if (dir) { if (best_pos > pos) { found = 1; best_pos = pos; fpos = ind - s->seq; fseq = r->rec; } } else { if (best_pos < pos) { found = 1; best_pos = pos; fpos = ind - s->seq; fseq = r->rec; } } //printf("Matches #%"PRIrec": at abs pos %d\n", r->rec, pos); } if (s != sorig) free(s); } if (found) { edSetCursorPos(xx, fseq == xx->cnum ? GT_Contig : GT_Seq, fseq, fpos, 1); } free(uppert); free(upperb); contig_iter_del(iter); return found ? 0 : -1; }
static jl_get_ptls_states_func jl_get_ptls_states_resolve(void) { if (jl_tls_states_cb != jl_get_ptls_states_init) return jl_tls_states_cb; // If we can't find the static version, return the wrapper instead // of the slow version so that we won't resolve to the slow version // due to issues in the relocation order. // This may not be necessary once `ifunc` support in glibc is more mature. if (!jl_get_ptls_states_static) return jl_get_ptls_states_wrapper; jl_tls_states_cb = jl_get_ptls_states_static; return jl_tls_states_cb; } JL_DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void) __attribute__((ifunc ("jl_get_ptls_states_resolve"))); #else // JL_TLS_USE_IFUNC JL_DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void) { return jl_get_ptls_states_wrapper(); } #endif // JL_TLS_USE_IFUNC jl_get_ptls_states_func jl_get_ptls_states_getter(void) { if (jl_tls_states_cb == jl_get_ptls_states_init) jl_get_ptls_states_init(); // for codegen return jl_tls_states_cb; } # endif #else
int main(void){ int a; int* b; void* v; int c; int d; int e; int h; int i; int j; float f; float z; float x; float y; float* g; int zzz[20]; a=a/c*d/e*h/i/j; f=z*x**&y/f*f; a=*(b+a); a=zzz[23]; a=*(zzz+23); a=!a; if (!(a+b)) a=a; a=ffunc(a,b,f,g,v); a=gfunc(a,b,f,g); a=hfunc(a,b,f); a=ifunc(a,b); b=intstarfunc(a); g=floatstarfunc(f); v=voidstarfunc(v); return 1; /* g=g/g/g/g/g;*/ /* a=a+c; f=f+f; b=b+a; b=a+b; g=g+a; g=a+g; a=a-c; f=f-f; b=b-a; g=g-a; a=g-g; a=b-b;*/ }
typedef int (Func)(Klass*); typedef int (Klass::*MemFuncPtr)(); static Func* good_resolver (); static void* iffy_resolver (); static MemFuncPtr bad_resolver (); }; int Klass::implementation (void) { return 0; } // Verify no warning for the expected/compatible declaration. int __attribute__ ((ifunc ("_ZN5Klass13good_resolverEv"))) Klass::good_magic (); Klass::Func* Klass::good_resolver (void) { MemFuncPtr mfp = &Klass::implementation; return reinterpret_cast<Func*>(mfp); } // Verify a warning for the unsafe declaration. int __attribute__ ((ifunc ("_ZN5Klass13iffy_resolverEv"))) Klass::iffy_magic (); // { dg-message "resolver indirect function declared here" }
static bool avx2_support(void) { int a, b, c, d; if (__get_cpuid_max(0, NULL) < 7) { return false; } __cpuid_count(7, 0, a, b, c, d); return b & bit_AVX2; } bool can_use_buffer_find_nonzero_offset(const void *buf, size_t len) \ __attribute__ ((ifunc("can_use_buffer_find_nonzero_offset_ifunc"))); size_t buffer_find_nonzero_offset(const void *buf, size_t len) \ __attribute__ ((ifunc("buffer_find_nonzero_offset_ifunc"))); static void *buffer_find_nonzero_offset_ifunc(void) { typeof(buffer_find_nonzero_offset) *func = (avx2_support()) ? buffer_find_nonzero_offset_avx2 : buffer_find_nonzero_offset_inner; return func; } static void *can_use_buffer_find_nonzero_offset_ifunc(void) { typeof(can_use_buffer_find_nonzero_offset) *func = (avx2_support()) ? can_use_buffer_find_nonzero_offset_avx2 :
#include <stdio.h> static void mytest(int d) { printf("%d\n", d); } static void (*resolve_test(void))(void) { return (void (*)(void))&mytest; } void test(int d) __attribute__((ifunc("resolve_test"))); int main() { test(5); return 0; }
static Func* resolver (); }; int Klass::implementation (void) { printf ("'ere I am JH\n"); return 0; } Klass::Func* Klass::resolver (void) { /* GCC guarantees this conversion to be safe and the resulting pointer usable to call the member function using ordinary (i.e., non-member) function call syntax. */ return reinterpret_cast<Func*>(&Klass::implementation); } int Klass::magic (void) __attribute__ ((ifunc ("_ZN5Klass8resolverEv"))); struct Klassier : Klass { }; int main () { Klassier obj; return obj.magic () != 0; }
* distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdio.h> #include <stdlib.h> static int g_flag = 0; static void __attribute__((constructor)) init_flag() { g_flag = 1; } const char* foo() __attribute__ ((ifunc ("foo_ifunc"))); const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun"))); const char* return_true() { return "true"; } const char* return_false() { return "false"; } const char* f1() { return "unset"; } const char* f2() {
# define LOOP_NEED_FLAGS # define BODY BODY_FROM_C # include <iconv/loop.c> /* Generate loop-function with hardware vector instructions. */ # define MIN_NEEDED_INPUT MIN_NEEDED_FROM # define MAX_NEEDED_INPUT MAX_NEEDED_FROM # define MIN_NEEDED_OUTPUT MIN_NEEDED_TO # define LOOPFCT __from_utf16_loop_vx # define LOOP_NEED_FLAGS # define BODY BODY_FROM_VX # include <iconv/loop.c> /* Generate ifunc'ed loop function. */ __typeof(__from_utf16_loop_c) __attribute__ ((ifunc ("__from_utf16_loop_resolver"))) __from_utf16_loop; static void * __from_utf16_loop_resolver (unsigned long int dl_hwcap) { if (dl_hwcap & HWCAP_S390_VX) return __from_utf16_loop_vx; else return __from_utf16_loop_c; } strong_alias (__from_utf16_loop_c_single, __from_utf16_loop_single) #else # define LOOPFCT FROM_LOOP # define LOOP_NEED_FLAGS
if (UNLIKELY(needles.empty() || haystack.empty())) { return StringPiece::npos; } // The thresholds below were empirically determined by benchmarking. // This is not an exact science since it depends on the CPU, the size of // needles, and the size of haystack. if (haystack.size() == 1 || (haystack.size() < 4 && needles.size() <= 16)) { return qfind_first_of(haystack, needles, asciiCaseSensitive); } else if ((needles.size() >= 4 && haystack.size() <= 10) || (needles.size() >= 16 && haystack.size() <= 64) || needles.size() >= 32) { return qfind_first_byte_of_byteset(haystack, needles); } return qfind_first_byte_of_memchr(haystack, needles); } // This function is called on startup to resolve folly::qfind_first_byte_of extern "C" Type_qfind_first_byte_of* qfind_first_byte_of_ifunc() { return folly::CpuId().sse42() ? qfind_first_byte_of_sse42 : qfind_first_byte_of_nosse; } size_t qfind_first_byte_of(const StringPiece& haystack, const StringPiece& needles) __attribute__((ifunc("qfind_first_byte_of_ifunc"))); } // namespace detail } // namespace folly
return (func_t)&GOST34112012Final_sse41; } if (edx & bit_SSE2) { return (func_t)&GOST34112012Final_sse2; } if (edx & bit_MMX) { return (func_t)&GOST34112012Final_mmx; } } return (func_t)&GOST34112012Final_ref; } extern void GOST34112012Update(void* restrict ctx, const unsigned char* restrict data, size_t len) __attribute__((ifunc("resolve_GOST34112012Update"))); extern void GOST34112012Final(void* restrict ctx, unsigned char* restrict digest) __attribute__((ifunc("resolve_GOST34112012Final"))); #else void GOST34112012Update(void* restrict ctx, const unsigned char* restrict data, size_t len) { #if __SSE4_1__ GOST34112012Update_sse41(ctx, data, len); #elif __SSE2__ GOST34112012Update_sse2(ctx, data, len); #elif __MMX__ GOST34112012Update_mmx(ctx, data, len); #else GOST34112012Update_ref(ctx, data, len); #endif
int edview_search_tag_anno(edview *xx, int dir, int strand, char *value) { contig_iterator *iter; int start, end; rangec_t *r; rangec_t *(*ifunc)(GapIO *io, contig_iterator *ci); char *r_exp = NULL; contig_t *c = cache_search(xx->io, GT_Contig, xx->cnum); if (value) { if (NULL == (r_exp = REGCMP(xx->interp, value))) { verror(ERR_WARN, "Search by anno", "invalid regular expression"); return -1; } } if (dir) { start = xx->cursor_apos + (dir ? 1 : -1); end = c->end; ifunc = contig_iter_next; } else { start = c->start; end = xx->cursor_apos + (dir ? 1 : -1); ifunc = contig_iter_prev; } iter = contig_iter_new_by_type(xx->io, xx->cnum, 1, dir == 1 ? CITER_FIRST : CITER_LAST, start, end, GRANGE_FLAG_ISANNO); if (!iter) return -1; while (r = ifunc(xx->io, iter)) { anno_ele_t *ae; if ((dir && r->start < start) || (!dir && r->start > end)) continue; if (!r_exp) break; /* blank expr => match all */ ae = cache_search(xx->io, GT_AnnoEle, r->rec); if (!ae->comment) continue; if (REGEX(xx->interp, ae->comment, r_exp)) break; } REGFREE(xx->interp, r_exp); if (r) { if (r->flags & GRANGE_FLAG_TAG_SEQ) { int pos; sequence_get_position(xx->io, r->pair_rec, NULL, &pos, NULL, NULL); pos = r->start - pos; edSetCursorPos(xx, GT_Seq, r->pair_rec, pos, 1); } else { edSetCursorPos(xx, GT_Contig, xx->cnum, r->start, 1); } contig_iter_del(iter); return 0; } contig_iter_del(iter); return -1; }
static unsigned long __init finish_node(struct device_node *np, unsigned long mem_start, interpret_func *ifunc, int naddrc, int nsizec) { struct device_node *child; int *ip; np->name = get_property(np, "name", 0); np->type = get_property(np, "device_type", 0); if (!np->name) np->name = "<NULL>"; if (!np->type) np->type = "<NULL>"; /* get the device addresses and interrupts */ if (ifunc != NULL) mem_start = ifunc(np, mem_start, naddrc, nsizec); if (use_of_interrupt_tree) mem_start = finish_node_interrupts(np, mem_start); /* Look for #address-cells and #size-cells properties. */ ip = (int *) get_property(np, "#address-cells", 0); if (ip != NULL) naddrc = *ip; ip = (int *) get_property(np, "#size-cells", 0); if (ip != NULL) nsizec = *ip; if (np->parent == NULL) ifunc = interpret_root_props; else if (np->type == 0) ifunc = NULL; else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) ifunc = interpret_pci_props; else if (!strcmp(np->type, "dbdma")) ifunc = interpret_dbdma_props; else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) ifunc = interpret_macio_props; else if (!strcmp(np->type, "isa")) ifunc = interpret_isa_props; else if (!strcmp(np->name, "uni-n")) ifunc = interpret_root_props; else if (!((ifunc == interpret_dbdma_props || ifunc == interpret_macio_props) && (!strcmp(np->type, "escc") || !strcmp(np->type, "media-bay")))) ifunc = NULL; /* if we were booted from BootX, convert the full name */ if (boot_infos && strncmp(np->full_name, "Devices:device-tree", 19) == 0) { if (np->full_name[19] == 0) { strcpy(np->full_name, "/"); } else if (np->full_name[19] == ':') { char *p = np->full_name + 19; np->full_name = p; for (; *p; ++p) if (*p == ':') *p = '/'; } } for (child = np->child; child != NULL; child = child->sibling) mem_start = finish_node(child, mem_start, ifunc, naddrc, nsizec); return mem_start; }
/* * Attempt to find edits. It's not 100% reliable, but works for most cases. * We look for lowercase bases and confidence 100 and 0 (if not N). * We cannot find deleted bases though. */ int edview_search_edit(edview *xx, int dir, int strand, char *value) { int start, end; contig_iterator *iter; rangec_t *(*ifunc)(GapIO *io, contig_iterator *ci); rangec_t *r; int best_pos, found = 0; int fpos; tg_rec fseq; if (dir) { start = xx->cursor_apos + 1; end = CITER_CEND; iter = contig_iter_new(xx->io, xx->cnum, 1, CITER_FIRST | CITER_ISTART, start, end); ifunc = contig_iter_next; best_pos = INT_MAX; } else { start = CITER_CSTART; end = xx->cursor_apos -1; iter = contig_iter_new(xx->io, xx->cnum, 1, CITER_LAST | CITER_IEND, start, end); ifunc = contig_iter_prev; best_pos = INT_MIN; } if (!iter) return -1; while ((r = ifunc(xx->io, iter))) { seq_t *s, *sorig; char *seq, *qual; int seq_len, comp, off = 0, i; if (found && dir && r->start > best_pos) break; if (found && !dir && r->end < best_pos) break; if (NULL == (s = sorig = cache_search(xx->io, GT_Seq, r->rec))) break; if (r->comp ^ (s->len < 0)) { s = dup_seq(s); complement_seq_t(s); } seq = s->seq; qual = s->conf; seq_len = ABS(s->len); if (r->start < start) { off = start - r->start; seq += off; qual += off; seq_len -= off; } for (i = 0; i < seq_len; i++) { if (islower(seq[i]) || qual[i] == 100 || (qual[i] == 0 && seq[i] != 'N' && seq[i] != '-' && seq[i] != '*')) { int pos = r->start + i + off; if (dir) { if (best_pos > pos && pos > xx->cursor_apos) { found = 1; best_pos = pos; fpos = i + off; fseq = r->rec; } break; } else { if (best_pos < pos && pos < xx->cursor_apos) { found = 1; best_pos = pos; fpos = i + off; fseq = r->rec; } } } } if (s != sorig) free(s); } if (found) { edSetCursorPos(xx, fseq == xx->cnum ? GT_Contig : GT_Seq, fseq, fpos, 1); } contig_iter_del(iter); return found ? 0 : -1; }
/** stdcall: * C Naming - Name prefixed by a '_', followed by the name, then an '@', followed by number of bytes in arguments. i.e. foo(int a, double b) = _foo@12 * C++ Naming - __stdcall * Args - Arguments are passed on the stack. * Cleanup - Callee cleans up the stack before returning cdecl: * C Naming - Name prefixed by a '_' * C++ Naming - __cdecl in demangled name * Args - Arguments are passed on the stack. * Cleanup - Caller cleans up the stack after the return fastcall: * C Naming - Name prefixed by a '@', followed by the func name, then another '@', followed by the number of bytes in the arguments. i.e. foo(double a, int b, int c, int d) = @foo@20 * C++ Naming - __fastcall in the mangled name * Args - First two arguments that are less than DWORD size are passed in ECX & EDX * Cleanup - Callee cleans up the stack before returning thiscall: * C Naming - NA * C++ Naming - __thiscall in the demangled name * 'this' parameter is passed in ECX, others are passed in the stack * Cleanup Callee cleans up the stack before returning **/ callType func_instance::getCallingConvention() { std::cerr << "symtab name (c++): " << symTabName() << std::endl; //const char *name = symTabName().c_str(); const int buffer_size = 1024; char buffer[buffer_size]; int pos; if (callingConv != unknown_call) return callingConv; if (symTabName().empty()) { assert(0); //Umm... return unknown_call; } switch(symTabName()[0]) { case '?': //C++ Encoded symbol. Everything is stored in the C++ name // mangling scheme UnDecorateSymbolName(symTabName().c_str(), buffer, buffer_size, UNDNAME_NO_ARGUMENTS | UNDNAME_NO_FUNCTION_RETURNS); printf("undecorated name: %s\n", buffer); if (strstr(buffer, "__thiscall")) { callingConv = thiscall_call; return callingConv; } if (strstr(buffer, "__fastcall")) { callingConv = fastcall_call; return callingConv; } if (strstr(buffer, "__stdcall")) { callingConv = stdcall_call; return callingConv; } if (strstr(buffer, "__cdecl")) { callingConv = cdecl_call; return callingConv; } break; case '_': //Check for stdcall or cdecl pos = symTabName().find('@'); if (pos != std::string::npos) { callingConv = stdcall_call; return callingConv; } else { callingConv = cdecl_call; return callingConv; } break; case '@': //Should be a fast call pos = symTabName().find('@'); if (pos != std::string::npos) { callingConv = fastcall_call; return callingConv; } break; } //We have no idea what this call is. We probably got an undecorated // name. If the function doesn't clean up it's own stack (doesn't // have a ret #) instruction, then it must be a cdecl call, as that's // the only type that doesn't clean its own stack. //If the function is part of a class, then it's most likely a thiscall, // although that could be incorrect for a static function. //Otherwise let's guess that it's a stdcall. if (!ifunc()->cleansOwnStack()) { callingConv = cdecl_call; } else if (symTabName().find("::") != std::string::npos) { callingConv = thiscall_call; } else { callingConv = stdcall_call; } return callingConv; }
/* { dg-do run } */ /* { dg-require-ifunc "" } */ /* { dg-options "" } */ #include <stdio.h> static int implementation (void) { printf ("'ere I am JH\n"); return 0; } static void *resolver (void) { return (void *)implementation; } extern int magic (void) __attribute__ ((ifunc ("resolver"))); int main () { return magic () != 0; }
int foo (int x) __attribute__ ((ifunc ("resolve_foo"))); static int foo_impl(int x) { return x; } void *resolve_foo (void) { return (void *) foo_impl; }