📄 libgcc2.c
字号:
asm (" sw $4,0($30)"); asm (" sw $5,4($30)"); asm (" sw $6,8($30)"); asm (" sw $7,12($30)"); asm (" j $31"); asm (" .end __builtin_saveregs");#else /* not __mips__, etc. */__builtin_saveregs (){ abort ();}#endif /* not __mips__ */#endif /* not __sparc__ */#endif /* not __i860__ */#endif#ifdef L_eprintf#ifndef inhibit_eprintf#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */#include <stdio.h>/* This is used by the `assert' macro. */void__eprintf (string, expression, line, filename) const char *string; const char *expression; int line; const char *filename;{ fprintf (stderr, string, expression, line, filename); fflush (stderr); abort ();}#endif#endif#ifdef L_bb/* Avoid warning from ranlib about empty object file. */void__bb_avoid_warning (){}#if defined (__sun__) && defined (__mc68000__)struct bb{ int initialized; char *filename; int *counts; int ncounts; int zero_word; int *addresses;};extern int ___tcov_init;__bb_init_func (blocks) struct bb *blocks;{ if (! ___tcov_init) ___tcov_init_func (); ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);}#endif#endif/* frills for C++ */#ifdef L_builtin_new#include <sys/types.h>typedef void (*vfp)(void);extern vfp __new_handler;void *__builtin_new (sz) size_t sz;{ void *p; /* malloc (0) is unpredictable; avoid it. */ if (sz == 0) sz = 1; p = (void *) malloc (sz); if (p == 0) (*__new_handler) (); return p;}#endif#ifdef L_caps_New/* This gets us __GNU_LIBRARY__. */#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */#include <stdio.h>#include <sys/types.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))#endiftypedef void (*vfp)(void);extern void *__builtin_new (size_t);static void default_new_handler (void);vfp __new_handler = default_new_handler;void *__builtin_vec_new (p, maxindex, size, ctor) void *p; size_t maxindex; size_t size; void (*ctor)(void *);{ size_t i; size_t nelts = maxindex + 1; void *rval; if (p == 0) p = __builtin_new (nelts * size); rval = p; for (i = 0; i < nelts; i++) { (*ctor) (p); p += size; } return rval;}vfp__set_new_handler (handler) vfp handler;{ vfp prev_handler; prev_handler = __new_handler; if (handler == 0) handler = default_new_handler; __new_handler = handler; return prev_handler;}vfpset_new_handler (handler) vfp handler;{ return __set_new_handler (handler);}#define MESSAGE "Virtual memory exceeded in `new'\n"static voiddefault_new_handler (){ /* 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)); /* don't call exit () because that may call global destructors which may cause a loop. */ _exit (-1);}#endif#ifdef L_builtin_del#include <sys/types.h>typedef void (*vfp)(void);void__builtin_delete (ptr) void *ptr;{ if (ptr) free (ptr);}void__builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete) void *ptr; size_t maxindex; size_t size; void (*dtor)(void *, int); int auto_delete;{ size_t i; size_t nelts = maxindex + 1; void *p = ptr; ptr += nelts * size; for (i = 0; i < nelts; i++) { ptr -= size; (*dtor) (ptr, auto_delete); } if (auto_delete_vec) __builtin_delete (p);}#endif#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 (beg, end) char *beg, *end;{#ifdef INSN_CACHE_SIZE static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH]; static int initialized = 0; 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 /* L_clear_cache */#ifdef L_trampoline/* Jump to a trampoline, loading the static chain address. */#ifdef TRANSFER_FROM_TRAMPOLINE TRANSFER_FROM_TRAMPOLINE #endif#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 __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"/* Run all the global destructors on exit from the program. */void__do_global_dtors (){#ifdef DO_GLOBAL_DTORS_BODY DO_GLOBAL_DTORS_BODY;#else unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0]; unsigned i; /* Some systems place the number of pointers in the first word of the table. On other systems, that word is -1. In all cases, the table is null-terminated. */ /* If the length is not recorded, count up to the null. */ if (nptrs == -1) for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); /* GNU LD format. */ for (i = nptrs; i >= 1; i--) __DTOR_LIST__[i] ();#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. */void__main (){ /* Support recursive calls to `main': run initializers just once. */ static int initialized = 0; 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)#ifdef __NeXT__/* 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 volatile void _exit ();void exit (status) int status;{ __do_global_dtors ();#ifdef EXIT_BODY EXIT_BODY;#else _cleanup ();#endif _exit (status);}#elseint _exit_dummy_decl = 0; /* prevent compiler & linker warnings */#endif#endif /* L_exit *//* In a.out systems, we need to have these dummy constructor and destructor lists in the library. When using `collect', the first link will resolve __CTOR_LIST__ and __DTOR_LIST__ to these symbols. We will then run "nm" on the result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink. Since we don't do the second link if no constructors existed, these dummies must be fully functional empty lists. When using `gnu ld', these symbols will be used if there are no constructors. If there are constructors, the N_SETV symbol defined by the linker from the N_SETT's in input files will define __CTOR_LIST__ and __DTOR_LIST__ rather than its being allocated as common storage by the definitions below. When using a linker that supports constructor and destructor segments, these definitions will not be used, since crtbegin.o and crtend.o (from crtstuff.c) will have already defined __CTOR_LIST__ and __DTOR_LIST__. The crt*.o files are passed directly to the linker on its command line, by gcc. *//* The list needs two elements: one is ignored (the old count); the second is the terminating zero. Since both values are zero, this declaration is not initialized, and it becomes `common'. */#ifdef L_ctor_list#include "gbl-ctors.h"func_ptr __CTOR_LIST__[2];#endif#ifdef L_dtor_list#include "gbl-ctors.h"func_ptr __DTOR_LIST__[2];#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -