diff options
Diffstat (limited to 'sysdeps/powerpc')
-rw-r--r-- | sysdeps/powerpc/elf/libc-start.c | 23 | ||||
-rw-r--r-- | sysdeps/powerpc/elf/start.S | 11 | ||||
-rw-r--r-- | sysdeps/powerpc/register-dump.h | 109 |
3 files changed, 99 insertions, 44 deletions
diff --git a/sysdeps/powerpc/elf/libc-start.c b/sysdeps/powerpc/elf/libc-start.c index 535eab2a64..e90553a154 100644 --- a/sysdeps/powerpc/elf/libc-start.c +++ b/sysdeps/powerpc/elf/libc-start.c @@ -25,6 +25,7 @@ extern void __libc_init_first (int argc, char **argv, char **envp); extern int _dl_starting_up; weak_extern (_dl_starting_up) extern int __libc_multiple_libcs; +extern void *__libc_stack_end; struct startup_info { @@ -67,13 +68,17 @@ __libc_start_main (int argc, char **argv, char **envp, rtld_fini = NULL; } - /* Register the destructor of the dynamic linker if there is any. */ - if (rtld_fini != NULL) - atexit (rtld_fini); + /* Store something that has some relationship to the end of the + stack, for backtraces. This variable should be thread-specific. */ + __libc_stack_end = stack_on_entry + 4; /* Set the global _environ variable correctly. */ __environ = envp; + /* Register the destructor of the dynamic linker if there is any. */ + if (rtld_fini != NULL) + atexit (rtld_fini); + /* Call the initializer of the libc. */ #ifdef PIC if (_dl_debug_impcalls) @@ -81,15 +86,17 @@ __libc_start_main (int argc, char **argv, char **envp, #endif __libc_init_first (argc, argv, envp); - /* Call the initializer of the program. */ + /* Register the destructor of the program, if any. */ + if (stinfo->fini) + atexit (stinfo->fini); + + /* Call the initializer of the program, if any. */ #ifdef PIC if (_dl_debug_impcalls) _dl_debug_message (1, "\ninitialize program: ", argv[0], "\n\n", NULL); #endif - stinfo->init (argc, argv, __environ, auxvec); - - /* Register the destructor of the program. */ - atexit (stinfo->fini); + if (stinfo->init) + stinfo->init (argc, argv, __environ, auxvec); #ifdef PIC if (_dl_debug_impcalls) diff --git a/sysdeps/powerpc/elf/start.S b/sysdeps/powerpc/elf/start.S index 94cb423629..a52ac8b64d 100644 --- a/sysdeps/powerpc/elf/start.S +++ b/sysdeps/powerpc/elf/start.S @@ -7,6 +7,15 @@ published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + In addition to the permissions in the GNU Library General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Library General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -22,6 +31,8 @@ /* These are the various addresses we require. */ .section ".rodata" .align 2 + weak_extern(_init) + weak_extern(_fini) L(start_addresses): .long _SDA_BASE_ .long JUMPTARGET(main) diff --git a/sysdeps/powerpc/register-dump.h b/sysdeps/powerpc/register-dump.h index 428b6073b9..2e15c0bd71 100644 --- a/sysdeps/powerpc/register-dump.h +++ b/sysdeps/powerpc/register-dump.h @@ -1,7 +1,6 @@ /* Dump registers. Copyright (C) 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -21,53 +20,91 @@ #include <sys/uio.h> #include <stdio-common/_itoa.h> -static const char *regnames[] = -{ - "\nr0 =", " sp =", " r2 =", " r3 =", " r4 =", " r5 =", - "\nr6 =", " r7 =", " r8 =", " r9 =", " r10=", " r11=", - "\nr12=", " r13=", " r14=", " r15=", " r16=", " r17=", - "\nr18=", " r19=", " r20=", " r21=", " r22=", " r23=", - "\nr24=", " r25=", " r26=", " r27=", " r28=", " r29=", - "\nr30=", " r31=", " nip=", " msr=", " r3*=", " ctr=", - "\nlr =", " xer=", " ccr=", " mq =", " trap=", - "\naddress of fault=", " dsisr=", -}; +/* This prints out the information in the following form: */ +static const char dumpform[] = +"Register dump:\n\ +r0 =0000000% sp =0000000% r2 =0000000% r3 =0000000% r4 =0000000% r5 =0000000% +r6 =0000000% r7 =0000000% r8 =0000000% r9 =0000000% r10=0000000% r11=0000000% +r12=0000000% r13=0000000% r14=0000000% r15=0000000% r16=0000000% r17=0000000% +r18=0000000% r19=0000000% r20=0000000% r21=0000000% r22=0000000% r23=0000000% +r24=0000000% r25=0000000% r26=0000000% r27=0000000% r28=0000000% r29=0000000% +r30=0000000% r31=0000000% sr0=0000000% msr=0000000% r3*=0000000% ctr=0000000% +lr =0000000% xer=0000000% ccr=0000000% sr1=0000000% trap=0000000% +address of fault=0000000% dsisr=0000000%\n"; +/* Most of the fields are self-explanatory. 'sr0' is the next + instruction to execute, from SRR0, which may have some relationship + with the instruction that caused the exception. 'r3*' is the value + that will be returned in register 3 when the current system call + returns. 'sr1' is SRR1, bits 16-31 of which are copied from the MSR: + + 16 - External interrupt enable + 17 - Privilege level (1=user, 0=supervisor) + 18 - FP available + 19 - Machine check enable (if clear, processor locks up on machine check) + 20 - FP exception mode bit 0 (FP exceptions recoverable) + 21 - Single-step trace enable + 22 - Branch trace enable + 23 - FP exception mode bit 1 + 25 - exception prefix (if set, exceptions are taken from 0xFFFnnnnn, + otherwise from 0x000nnnnn). + 26 - Instruction address translation enabled. + 27 - Data address translation enabled. + 30 - Exception is recoverable (otherwise, don't try to return). + 31 - Little-endian mode enable. + + 'Trap' is the address of the exception: + + 00200 - Machine check exception (memory parity error, for instance) + 00300 - Data access exception (memory not mapped, see dsisr for why) + 00400 - Instruction access exception (memory not mapped) + 00500 - External interrupt + 00600 - Alignment exception (see dsisr for more information) + 00700 - Program exception (illegal/trap instruction, FP exception) + 00800 - FP unavailable (should not be seen by user code) + 00900 - Decrementer exception (for instance, SIGALRM) + 00A00 - I/O controller interface exception + 00C00 - System call exception (for instance, kill(3)). + 00E00 - FP assist exception (optional FP instructions, etc.) + + 'address of fault' is the memory location that wasn't mapped + (from the DAR). 'dsisr' has the following bits under trap 00300: + 0 - direct-store error exception + 1 - no page table entry for page + 4 - memory access not permitted + 5 - trying to access I/O controller space or using lwarx/stwcx on + non-write-cached memory + 6 - access was store + 9 - data access breakpoint hit + 10 - segment table search failed to find translation (64-bit ppcs only) + 11 - I/O controller instruction not permitted + For trap 00400, the same bits are set in SRR1 instead. + For trap 00600, bits 12-31 of the DSISR set to allow emulation of + the instruction without actually having to read it from memory. +*/ static void register_dump (int fd, void **ctx) { - char buffer[(sizeof (regnames) / sizeof (regnames[0])) * 8]; - char *bufferpos = buffer + sizeof (buffer); - struct iovec iov[(sizeof (regnames) / sizeof (regnames[0])) * 2 + 1]; - int nr = 0; - -#define ADD_STRING(str) \ - iov[nr].iov_base = (char *) str; \ - iov[nr].iov_len = strlen (str); \ - ++nr -#define ADD_HEX(str, len) \ - do { \ - char *s = _itoa_word ((unsigned long int) x, bufferpos, 16, 0); \ - while (bufferpos - s < 8) \ - *--s = '0'; \ - iov[nr].iov_base = s; \ - iov[nr].iov_len = bufferpos - s; \ - bufferpos = s; \ - } while (0) + char buffer[sizeof(dumpform)]; + char *bufferpos = buffer; + int i = 0; + + memcpy(buffer, dumpform, sizeof(dumpform)); + + ctx += 8; /* FIXME!!!! Why is this necessary? Is it necessary? */ /* Generate the output. */ - ADD_STRING ("Register dump:\n\n"); - for (i = 0; i < sizeof (regnames) / sizeof (regnames[0]); i++) + while ((bufferpos = memchr (bufferpos, '%', sizeof(dumpform)))) { - ADD_STRING (regnames[i]); - ADD_HEX (ctx[i]); + *bufferpos++ = '0'; + _itoa_word ((unsigned long int)(ctx[i]), bufferpos, 16, 0); + i++; } /* Write the output. */ - writev (fd, iov, nr); + write (fd, buffer, sizeof(buffer)); } #define REGISTER_DUMP \ - ctx += 8; /* FIXME!!!! Why is this necessary? Is it necessary? */ \ register_dump (fd, ctx) |