📄 libgcc2.c
字号:
{ *(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. */#ifdef WINNTlong getpagesize(){#ifdef _ALPHA_ return 8192;#else return 4096;#endif}int mprotect(addr, len, prot) char *addr; int len, 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 (addr) 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 __DOLPHIN__/* 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 /* __DOLPHIN__ */#ifdef __pyr__#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */#include <stdio.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/param.h>#include <sys/vmmac.h>/* Modified from the convex -code above. mremap promises to clear the i-cache. */void__enable_execute_stack (){ int fp; if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ, PROT_READ|PROT_WRITE|PROT_EXEC)) { perror ("mprotect in __enable_execute_stack"); fflush (stderr); abort (); }}#endif /* __pyr__ */#endif /* L_trampoline */#ifdef L__main#include "gbl-ctors.h"/* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to give the same symbol without quotes for an alternative entry point. You must define both, or neither. */#ifndef NAME__MAIN#define NAME__MAIN "__main"#define SYMBOL__MAIN __main#endif#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)/* Run all the global destructors on exit from the program. */void__do_global_dtors (){#ifdef DO_GLOBAL_DTORS_BODY DO_GLOBAL_DTORS_BODY;#else func_ptr *p; for (p = __DTOR_LIST__ + 1; *p; ) (*p++) ();#endif}#endif#ifndef INIT_SECTION_ASM_OP/* Run all the global constructors on entry to the program. */#ifndef ON_EXIT#define ON_EXIT(a, b)#else/* Make sure the exit routine is pulled in to define the globals as bss symbols, just in case the linker does not automatically pull bss definitions from the library. */extern int _exit_dummy_decl;int *_exit_dummy_ref = &_exit_dummy_decl;#endif /* ON_EXIT */void__do_global_ctors (){ DO_GLOBAL_CTORS_BODY; ON_EXIT (__do_global_dtors, 0);}#endif /* no INIT_SECTION_ASM_OP */#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)/* Subroutine called automatically by `main'. Compiling a global function named `main' produces an automatic call to this function at the beginning. For many systems, this routine calls __do_global_ctors. For systems which support a .init section we use the .init section to run __do_global_ctors, so we need not do anything here. */voidSYMBOL__MAIN (){ /* Support recursive calls to `main': run initializers just once. */ static int initialized; if (! initialized) { initialized = 1; __do_global_ctors (); }}#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */#endif /* L__main */#ifdef L_ctors#include "gbl-ctors.h"/* Provide default definitions for the lists of constructors and destructors, so that we don't get linker errors. These symbols are intentionally bss symbols, so that gld and/or collect will provide the right values. *//* We declare the lists here with two elements each, so that they are valid empty lists if no other definition is loaded. */#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)#if defined(__NeXT__) || defined(_AIX)/* After 2.3, try this definition on all systems. */func_ptr __CTOR_LIST__[2] = {0, 0};func_ptr __DTOR_LIST__[2] = {0, 0};#elsefunc_ptr __CTOR_LIST__[2];func_ptr __DTOR_LIST__[2];#endif#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */#endif /* L_ctors */#ifdef L_exit#include "gbl-ctors.h"#ifndef ON_EXIT/* If we have no known way of registering our own __do_global_dtors routine so that it will be invoked at program exit time, then we have to define our own exit routine which will get this to happen. */extern void __do_global_dtors ();extern void _cleanup ();extern void _exit () __attribute__ ((noreturn));void exit (status) int status;{#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) __do_global_dtors ();#endif#ifdef EXIT_BODY EXIT_BODY;#else _cleanup ();#endif _exit (status);}#elseint _exit_dummy_decl = 0; /* prevent compiler & linker warnings */#endif#endif /* L_exit */#ifdef L_ehtypedef struct { void *start; void *end; void *exception_handler;} exception_table;struct exception_table_node { exception_table *table; void *start; void *end; struct exception_table_node *next;};static int except_table_pos;static void *except_pc;static struct exception_table_node *exception_table_list;static exception_table *find_exception_table (pc) void* pc;{ register struct exception_table_node *table = exception_table_list; for ( ; table != 0; table = table->next) { if (table->start <= pc && table->end > pc) return table->table; } return 0;}/* this routine takes a pc, and the address of the exception handler associated with the closest exception table handler entry associated with that PC, or 0 if there are no table entries the PC fits in. The algorithm works something like this: while(current_entry exists) { if(current_entry.start < pc ) current_entry = next_entry; else { if(prev_entry.start <= pc && prev_entry.end > pc) { save pointer to prev_entry; return prev_entry.exception_handler; } else return 0; } } return 0; Assuming a correctly sorted table (ascending order) this routine should return the tightest match... In the advent of a tie, we have to give the last entry, as it represents an inner block. */void *__find_first_exception_table_match(pc)void *pc;{ exception_table *table = find_exception_table (pc); int pos = 0; int best = 0; if (table == 0) return (void*)0;#if 0 printf("find_first_exception_table_match(): pc = %x!\n",pc);#endif except_pc = pc;#if 0 /* We can't do this yet, as we don't know that the table is sorted. */ do { ++pos; if (table[pos].start > except_pc) /* found the first table[pos].start > except_pc, so the previous entry better be the one we want! */ break; } while(table[pos].exception_handler != (void*)-1); --pos; if (table[pos].start <= except_pc && table[pos].end > except_pc) { except_table_pos = pos;#if 0 printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);#endif return table[pos].exception_handler; }#else while (table[++pos].exception_handler != (void*)-1) { if (table[pos].start <= except_pc && table[pos].end > except_pc) { /* This can apply. Make sure it is better or as good as the previous best. */ /* The best one ends first. */ if (best == 0 || (table[pos].end <= table[best].end /* The best one starts last. */ && table[pos].start >= table[best].start)) best = pos; } } if (best != 0) return table[best].exception_handler;#endif#if 0 printf("find_first_eh_table_match(): else: returning NULL!\n");#endif return (void*)0;}void *__throw_type_match (void *catch_type, void *throw_type, void* obj){#if 0 printf("__throw_type_match (): catch_type = %s, throw_type = %s\n", catch_type, throw_type);#endif if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0) return obj; return 0;}void__register_exceptions (exception_table *table){ struct exception_table_node *node; exception_table *range = table + 1; if (range->start == (void*)-1) return; node = (struct exception_table_node*) malloc (sizeof (struct exception_table_node)); node->table = table; /* This look can be optimized away either if the table is sorted, or if we pass in extra parameters. */ node->start = range->start; node->end = range->end; for (range++ ; range->start != (void*)(-1); range++) { if (range->start < node->start) node->start = range->start; if (range->end > node->end) node->end = range->end; } node->next = exception_table_list; exception_table_list = node;}#if #machine(i386)void__unwind_function(void *ptr){ asm("movl 8(%esp),%ecx"); /* Undo current frame */ asm("movl %ebp,%esp"); asm("popl %ebp"); /* like ret, but stay here */ asm("addl $4,%esp"); /* Now, undo previous frame. */ /* This is a test routine, as we have to dynamically probe to find out what to pop for certain, this is just a guess. */ asm("leal -16(%ebp),%esp"); asm("pop %ebx"); asm("pop %esi"); asm("pop %edi"); asm("movl %ebp,%esp"); asm("popl %ebp"); asm("movl %ecx,0(%esp)"); asm("ret");}#elif #machine(rs6000)__unwind_function(void *ptr){ asm("mr 31,1"); asm("l 1,0(1)"); asm("l 31,-4(1)"); asm("# br"); asm("mr 31,1"); asm("l 1,0(1)"); /* use 31 as a scratch register to restore the link register. */ asm("l 31, 8(1);mtlr 31 # l lr,8(1)"); asm("l 31,-4(1)"); asm("# br"); asm("mtctr 3;bctr # b 3");}#elif #machine(powerpc)__unwind_function(void *ptr){ asm("mr 31,1"); asm("lwz 1,0(1)"); asm("lwz 31,-4(1)"); asm("# br"); asm("mr 31,1"); asm("lwz 1,0(1)"); /* use 31 as a scratch register to restore the link register. */ asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)"); asm("lwz 31,-4(1)"); asm("# br"); asm("mtctr 3;bctr # b 3");}#elif #machine(vax)__unwind_function(void *ptr){ __label__ return_again; /* Replace our frame's return address with the label below. During execution, we will first return here instead of to caller, then second return takes caller's frame off the stack. Two returns matches two actual calls, so is less likely to confuse debuggers. `16' corresponds to RETURN_ADDRESS_OFFSET. */ __asm ("movl %0,16(fp)" : : "p" (&& return_again)); return; return_again: return;}#else__unwind_function(void *ptr){ abort ();}#endif /* powerpc */#endif /* L_eh */#ifdef L_pure#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 */#define MESSAGE "pure virtual method called\n"void__pure_virtual (){#ifndef inhibit_libc write (2, MESSAGE, sizeof (MESSAGE) - 1);#endif _exit (-1);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -