📄 libgcc2.c
字号:
bucket->next = *startbucket; *startbucket = bucket; bucket->count = 1; } }ret: bb_dst = bb_src;skip: ;}/* Called upon entering the first function of a file. */static void__bb_init_file (struct bb *blocks){ const struct bb_func *p; long blk, ncounts = blocks->ncounts; const char **functions = blocks->functions; /* Set up linked list. */ blocks->zero_word = 1; blocks->next = bb_head; bb_head = blocks; blocks->flags = 0; if (!bb_func_head || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts))) return; for (blk = 0; blk < ncounts; blk++) blocks->flags[blk] = 0; for (blk = 0; blk < ncounts; blk++) { for (p = bb_func_head; p; p = p->next) { if (!strcmp (p->funcname, functions[blk]) && (!p->filename || !strcmp (p->filename, blocks->filename))) { blocks->flags[blk] |= p->mode; } } }}/* Called when exiting from a function. */void__bb_trace_ret (){ MACHINE_STATE_SAVE("2") if (bb_callcount) { if ((bb_mode & 12) && bb_stacksize > bb_callcount) { bb_src = bb_stack[bb_callcount]; if (bb_mode & 8) __bb_trace_func_ret (); } bb_callcount -= 1; } MACHINE_STATE_RESTORE("2")}/* Called when entering a function. */void__bb_init_trace_func (struct bb *blocks, unsigned long blockno){ static int trace_init = 0; MACHINE_STATE_SAVE("3") if (!blocks->zero_word) { if (!trace_init) { trace_init = 1; __bb_init_prg (); } __bb_init_file (blocks); } if (bb_callcount) { bb_callcount += 1; if (bb_mode & 12) { if (bb_callcount >= bb_stacksize) { size_t newsize = bb_callcount + 100; bb_stack = (unsigned long *) realloc (bb_stack, newsize); if (! bb_stack) { if (!reported) { fprintf (stderr, "Profiler: out of memory\n"); reported = 1; } bb_stacksize = 0; goto stack_overflow; } bb_stacksize = newsize; } bb_stack[bb_callcount] = bb_src; if (bb_mode & 4) bb_src = 0; }stack_overflow:; } else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON)) { bb_callcount = 1; bb_src = 0; if (bb_stack) bb_stack[bb_callcount] = bb_src; } MACHINE_STATE_RESTORE("3")}#endif /* not inhibit_libc */#endif /* not BLOCK_PROFILER_CODE */#endif /* L_bb *//* Default free-store management functions for C++, per sections 12.5 and 17.3.3 of the Working Paper. */#ifdef L_op_new/* operator new (size_t), described in 17.3.3.5. This function is used by C++ programs to allocate a block of memory to hold a single object. */typedef void (*vfp)(void);extern vfp __new_handler;extern void __default_new_handler (void);#ifdef WEAK_ALIASvoid * __builtin_new (size_t sz) __attribute__ ((weak, alias ("___builtin_new")));void *___builtin_new (size_t sz)#elsevoid *__builtin_new (size_t sz)#endif{ void *p; vfp handler = (__new_handler) ? __new_handler : __default_new_handler; /* malloc (0) is unpredictable; avoid it. */ if (sz == 0) sz = 1; p = (void *) malloc (sz); while (p == 0) { (*handler) (); p = (void *) malloc (sz); } return p;}#endif /* L_op_new */#ifdef L_op_vnew/* void * operator new [] (size_t), described in 17.3.3.6. This function is used by C++ programs to allocate a block of memory for an array. */extern void * __builtin_new (size_t);#ifdef WEAK_ALIASvoid * __builtin_vec_new (size_t sz) __attribute__ ((weak, alias ("___builtin_vec_new")));void *___builtin_vec_new (size_t sz)#elsevoid *__builtin_vec_new (size_t sz)#endif{ return __builtin_new (sz);}#endif /* L_op_vnew */#ifdef L_new_handler/* set_new_handler (fvoid_t *) and the default new handler, described in 17.3.3.2 and 17.3.3.5. These functions define the result of a failure to allocate the amount of memory requested from operator new or new []. */#ifndef inhibit_libc/* This gets us __GNU_LIBRARY__. */#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */#include <stdio.h>#ifdef __GNU_LIBRARY__ /* Avoid forcing the library's meaning of `write' on the user program by using the "internal" name (for use within the library) */#define write(fd, buf, n) __write((fd), (buf), (n))#endif#endif /* inhibit_libc */typedef void (*vfp)(void);void __default_new_handler (void);vfp __new_handler = (vfp) 0;vfpset_new_handler (vfp handler){ vfp prev_handler; prev_handler = __new_handler; if (handler == 0) handler = __default_new_handler; __new_handler = handler; return prev_handler;}#define MESSAGE "Virtual memory exceeded in `new'\n"void__default_new_handler (){#ifndef inhibit_libc /* don't use fprintf (stderr, ...) because it may need to call malloc. */ /* This should really print the name of the program, but that is hard to do. We need a standard, clean way to get at the name. */ write (2, MESSAGE, sizeof (MESSAGE));#endif /* don't call exit () because that may call global destructors which may cause a loop. */ _exit (-1);}#endif#ifdef L_op_delete/* operator delete (void *), described in 17.3.3.3. This function is used by C++ programs to return to the free store a block of memory allocated as a single object. */#ifdef WEAK_ALIASvoid __builtin_delete (void *ptr) __attribute__ ((weak, alias ("___builtin_delete")));void___builtin_delete (void *ptr)#elsevoid__builtin_delete (void *ptr)#endif{ if (ptr) free (ptr);}#endif#ifdef L_op_vdel/* operator delete [] (void *), described in 17.3.3.4. This function is used by C++ programs to return to the free store a block of memory allocated as an array. */extern void __builtin_delete (void *);#ifdef WEAK_ALIASvoid __builtin_vec_delete (void *ptr) __attribute__ ((weak, alias ("___builtin_vec_delete")));void___builtin_vec_delete (void *ptr)#elsevoid__builtin_vec_delete (void *ptr)#endif{ __builtin_delete (ptr);}#endif/* End of C++ free-store management functions */#ifdef L_shtabunsigned int __shtab[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 };#endif#ifdef L_clear_cache/* Clear part of an instruction cache. */#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)void__clear_cache (char *beg, char *end){#ifdef CLEAR_INSN_CACHE CLEAR_INSN_CACHE (beg, end);#else#ifdef INSN_CACHE_SIZE static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH]; static int initialized; int offset; void *start_addr void *end_addr; typedef (*function_ptr) ();#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16 /* It's cheaper to clear the whole cache. Put in a series of jump instructions so that calling the beginning of the cache will clear the whole thing. */ if (! initialized) { int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) & -INSN_CACHE_LINE_WIDTH); int end_ptr = ptr + INSN_CACHE_SIZE; while (ptr < end_ptr) { *(INSTRUCTION_TYPE *)ptr = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH; ptr += INSN_CACHE_LINE_WIDTH; } *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION; initialized = 1; } /* Call the beginning of the sequence. */ (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1) & -INSN_CACHE_LINE_WIDTH)) ());#else /* Cache is large. */ if (! initialized) { int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) & -INSN_CACHE_LINE_WIDTH); while (ptr < (int) array + sizeof array) { *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION; ptr += INSN_CACHE_LINE_WIDTH; } initialized = 1; } /* Find the location in array that occupies the same cache line as BEG. */ offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1); start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1) & -INSN_CACHE_PLANE_SIZE) + offset); /* Compute the cache alignment of the place to stop clearing. */#if 0 /* This is not needed for gcc's purposes. */ /* If the block to clear is bigger than a cache plane, we clear the entire cache, and OFFSET is already correct. */ if (end < beg + INSN_CACHE_PLANE_SIZE)#endif offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1) & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1));#if INSN_CACHE_DEPTH > 1 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset; if (end_addr <= start_addr) end_addr += INSN_CACHE_PLANE_SIZE; for (plane = 0; plane < INSN_CACHE_DEPTH; plane++) { int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE; int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE; while (addr != stop) { /* Call the return instruction at ADDR. */ ((function_ptr) addr) (); addr += INSN_CACHE_LINE_WIDTH; } }#else /* just one plane */ do { /* Call the return instruction at START_ADDR. */ ((function_ptr) start_addr) (); start_addr += INSN_CACHE_LINE_WIDTH; } while ((start_addr % INSN_CACHE_SIZE) != offset);#endif /* just one plane */#endif /* Cache is large */#endif /* Cache exists */#endif /* CLEAR_INSN_CACHE */}#endif /* L_clear_cache */#ifdef L_trampoline/* Jump to a trampoline, loading the static chain address. */#if defined(WINNT) && ! defined(__CYGWIN32__)long getpagesize(){#ifdef _ALPHA_ return 8192;#else return 4096;#endif}#ifdef i386extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));#endifintmprotect (char *addr, int len, int prot){ int np, op; if (prot == 7) np = 0x40; else if (prot == 5) np = 0x20; else if (prot == 4) np = 0x10; else if (prot == 3) np = 0x04; else if (prot == 1) np = 0x02; else if (prot == 0) np = 0x01; if (VirtualProtect (addr, len, np, &op)) return 0; else return -1;}#endif#ifdef TRANSFER_FROM_TRAMPOLINE TRANSFER_FROM_TRAMPOLINE #endif#if defined (NeXT) && defined (__MACH__)/* Make stack executable so we can call trampolines on stack. This is called from INITIALIZE_TRAMPOLINE in next.h. */#ifdef NeXTStep21 #include <mach.h>#else #include <mach/mach.h>#endifvoid__enable_execute_stack (char *addr){ kern_return_t r; char *eaddr = addr + TRAMPOLINE_SIZE; vm_address_t a = (vm_address_t) addr; /* turn on execute access on stack */ r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL); if (r != KERN_SUCCESS) { mach_error("vm_protect VM_PROT_ALL", r); exit(1); } /* We inline the i-cache invalidation for speed */#ifdef CLEAR_INSN_CACHE CLEAR_INSN_CACHE (addr, eaddr);#else __clear_cache ((int) addr, (int) eaddr);#endif} #endif /* defined (NeXT) && defined (__MACH__) */#ifdef __convex__/* Make stack executable so we can call trampolines on stack. This is called from INITIALIZE_TRAMPOLINE in convex.h. */#include <sys/mman.h>#include <sys/vmparam.h>#include <machine/machparam.h>void__enable_execute_stack (){ int fp; static unsigned lowest = USRSTACK; unsigned current = (unsigned) &fp & -NBPG; if (lowest > current) { unsigned len = lowest - current; mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); lowest = current; } /* Clear instruction cache in case an old trampoline is in it. */ asm ("pich");}#endif /* __convex__ */#ifdef __sysV88__/* Modified from the convex -code above. */#include <sys/param.h>#include <errno.h>#include <sys/m88kbcs.h>void__enable_execute_stack (){ int save_errno; static unsigned long lowest = USRSTACK; unsigned long current = (unsigned long) &save_errno & -NBPC; /* Ignore errno being set. memctl sets errno to EINVAL whenever the address is seen as 'negative'. That is the case with the stack. */ save_errno=errno; if (lowest > current) { unsigned len=lowest-current; memctl(current,len,MCT_TEXT); lowest = current; } else memctl(current,NBPC,MCT_TEXT); errno=save_errno;}#endif /* __sysV88__ */#ifdef __sysV68__#include <sys/signal.h>#include <errno.h>/* Motorola forgot to put memctl.o in the libp version of libc881.a, so define it here, because we need it in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -