📄 libgcc2.c
字号:
/* If the file is not empty, and the number of counts in it is the
same, then merge them in. */
firstchar = fgetc (da_file);
if (firstchar == EOF)
{
if (ferror (da_file))
{
fprintf (stderr, "arc profiling: Can't read output file ");
perror (ptr->filename);
}
}
else
{
long n_counts = 0;
if (ungetc (firstchar, da_file) == EOF)
rewind (da_file);
if (__read_long (&n_counts, da_file, 8) != 0)
{
fprintf (stderr, "arc profiling: Can't read output file %s.\n",
ptr->filename);
continue;
}
if (n_counts == ptr->ncounts)
{
int i;
for (i = 0; i < n_counts; i++)
{
gcov_type v = 0;
if (__read_gcov_type (&v, da_file, 8) != 0)
{
fprintf (stderr,
"arc profiling: Can't read output file %s.\n",
ptr->filename);
break;
}
ptr->counts[i] += v;
}
}
}
rewind (da_file);
/* ??? Should first write a header to the file. Preferably, a 4 byte
magic number, 4 bytes containing the time the program was
compiled, 4 bytes containing the last modification time of the
source file, and 4 bytes indicating the compiler options used.
That way we can easily verify that the proper source/executable/
data file combination is being used from gcov. */
if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
{
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
}
else
{
int j;
gcov_type *count_ptr = ptr->counts;
int ret = 0;
for (j = ptr->ncounts; j > 0; j--)
{
if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
{
ret = 1;
break;
}
count_ptr++;
}
if (ret)
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
}
if (fclose (da_file) == EOF)
fprintf (stderr, "arc profiling: Error closing output file %s.\n",
ptr->filename);
}
return;
}
void
__bb_init_func (struct bb *blocks)
{
/* User is supposed to check whether the first word is non-0,
but just in case.... */
if (blocks->zero_word)
return;
/* Initialize destructor. */
if (!bb_head)
atexit (__bb_exit_func);
/* Set up linked list. */
blocks->zero_word = 1;
blocks->next = bb_head;
bb_head = blocks;
}
/* Called before fork or exec - write out profile information gathered so
far and reset it to zero. This avoids duplication or loss of the
profile information gathered so far. */
void
__bb_fork_func (void)
{
struct bb *ptr;
__bb_exit_func ();
for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
{
long i;
for (i = ptr->ncounts - 1; i >= 0; i--)
ptr->counts[i] = 0;
}
}
#endif /* not inhibit_libc */
#endif /* not BLOCK_PROFILER_CODE */
#endif /* L_bb */
#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 __attribute__((__unused__)),
char *end __attribute__((__unused__)))
{
#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) (void);
#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(__CYGWIN__) && ! defined (_UWIN)
long
getpagesize (void)
{
#ifdef _ALPHA_
return 8192;
#else
return 4096;
#endif
}
#ifdef __i386__
extern int VirtualProtect (char *, int, int, int *) __attribute__((NTAPI));
#endif
int
mprotect (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 /* WINNT && ! __CYGWIN__ && ! _UWIN */
#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>
#endif
void
__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 (void)
{
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 (void)
{
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 __clear_insn_cache below */
/* On older versions of this OS, no memctl or MCT_TEXT are defined;
hence we enable this stuff only if MCT_TEXT is #define'd. */
#ifdef MCT_TEXT
asm("\n\
global memctl\n\
memctl:\n\
movq &75,%d0\n\
trap &0\n\
bcc.b noerror\n\
jmp cerror%\n\
noerror:\n\
movq &0,%d0\n\
rts");
#endif
/* Clear instruction cache so we can call trampolines on stack.
This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
void
__clear_insn_cache (void)
{
#ifdef MCT_TEXT
int save_errno;
/* Preserve errno, because users would be surprised to have
errno changing without explicitly calling any system-call. */
save_errno = errno;
/* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
No need to use an address derived from _start or %sp, as 0 works also. */
memctl(0, 4096, MCT_TEXT);
errno = save_errno;
#endif
}
#endif /* __sysV68__ */
#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 (void)
{
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__ */
#if defined (sony_news) && defined (SYSTYPE_BSD)
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <syscall.h>
#include <machine/sysnews.h>
/* cacheflush function for NEWS-OS 4.2.
This function is called from trampoline-initialize code
defined in config/mips/mips.h. */
void
cacheflush (char *beg, int size, int flag)
{
if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
{
perror ("cache_flush");
fflush (stderr);
abort ();
}
}
#endif /* sony_news */
#endif /* L_trampoline */
#ifndef __CYGWIN__
#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
#ifdef INIT_SECTION_ASM_OP
#undef HAS_INIT_SECTION
#define HAS_INIT_SECTION
#endif
#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
code to run constructors. In that case, we need to handle EH here, too. */
#ifdef EH_FRAME_SECTION_NAME
#include "unwind-dw2-fde.h"
extern unsigned char __EH_FRAME_BEGIN__[];
#endif
/* Run all the global destructors on exit from the program. */
void
__do_global_dtors (void)
{
#ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY;
#else
static func_ptr *p = __DTOR_LIST__ + 1;
while (*p)
{
p++;
(*(p-1)) ();
}
#endif
#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
{
static int completed = 0;
if (! completed)
{
completed = 1;
__deregister_frame_info (__EH_FRAME_BEGIN__);
}
}
#endif
}
#endif
#ifndef HAS_INIT_SECTION
/* Run all the global constructors on entry to the program. */
void
__do_global_ctors (void)
{
#ifdef EH_FRAME_SECTION_NAME
{
static struct object object;
__register_frame_info (__EH_FRAME_BEGIN__, &object);
}
#endif
DO_GLOBAL_CTORS_BODY;
atexit (__do_global_dtors);
}
#endif /* no HAS_INIT_SECTION */
#if !defined (HAS_INIT_SECTION) || 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
SYMBOL__MAIN ()
{
/* Support recursive calls to `main': run initializers just once. */
static int initialized;
if (! initialized)
{
initialized = 1;
__do_global_ctors ();
}
}
#endif /* no HAS_INIT_SECTION or INVOKE__main */
#endif /* L__main */
#endif /* __CYGWIN__ */
#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 we are using the old "set" extensions to have the gnu linker
collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
must be in the bss/common section.
Long term no port should use those extensions. But many still do. */
#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
func_ptr __CTOR_LIST__[2] = {0, 0};
func_ptr __DTOR_LIST__[2] = {0, 0};
#else
func_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"
#ifdef NEED_ATEXIT
#ifndef ON_EXIT
# include <errno.h>
static func_ptr *atexit_chain = 0;
static long atexit_chain_length = 0;
static volatile long last_atexit_chain_slot = -1;
int
atexit (func_ptr func)
{
if (++last_atexit_chain_slot == atexit_chain_length)
{
atexit_chain_length += 32;
if (atexit_chain)
atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
* sizeof (func_ptr));
else
atexit_chain = (func_ptr *) malloc (atexit_chain_length
* sizeof (func_ptr));
if (! atexit_chain)
{
atexit_chain_length = 0;
last_atexit_chain_slot = -1;
errno = ENOMEM;
return (-1);
}
}
atexit_chain[last_atexit_chain_slot] = func;
return (0);
}
extern void _cleanup (void);
extern void _exit (int) __attribute__ ((__noreturn__));
void
exit (int status)
{
if (atexit_chain)
{
for ( ; last_atexit_chain_slot-- >= 0; )
{
(*atexit_chain[last_atexit_chain_slot + 1]) ();
atexit_chain[last_atexit_chain_slot + 1] = 0;
}
free (atexit_chain);
atexit_chain = 0;
}
#ifdef EXIT_BODY
EXIT_BODY;
#else
_cleanup ();
#endif
_exit (status);
}
#else /* ON_EXIT */
/* Simple; we just need a wrapper for ON_EXIT. */
int
atexit (func_ptr func)
{
return ON_EXIT (func);
}
#endif /* ON_EXIT */
#endif /* NEED_ATEXIT */
#endif /* L_exit */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -