-typedef struct {
- int fsize; /* file size */
- int fixedparms; /* number of fixed parms */
- int floatparms; /* number of float parms */
- unsigned int parminfo; /* parameter info.
- See /usr/include/sys/debug.h
- tbtable_ext.parminfo */
- int framesize; /* function frame size */
-} TracebackInfo;
-
-static TracebackInfo *retrieve_tracebackinfo
- PARAMS ((bfd *, struct coff_symbol *));
-
-/* Given a function symbol, return its traceback information. */
-
-static TracebackInfo *
-retrieve_tracebackinfo (abfd, cs)
- bfd *abfd;
- struct coff_symbol *cs;
-{
-#define TBTABLE_BUFSIZ 2000
-
- static TracebackInfo tbInfo;
- struct tbtable *ptb;
-
- static char buffer [TBTABLE_BUFSIZ];
-
- int *pinsn;
- int bytesread=0; /* total # of bytes read so far */
- int bufferbytes; /* number of bytes in the buffer */
- int functionstart;
-
- asection *textsec;
-
- /* FIXME: Should be looking through all sections, based on the
- address we are considering. Just using ".text" loses if more
- than one section has code in it. */
- textsec = bfd_get_section_by_name (abfd, ".text");
- if (!textsec)
- {
-#if 0
- /* If there is only data, no text, that is OK. */
- printf_unfiltered ("Unable to locate text section!\n");
-#endif
- return;
- }
-
- functionstart = cs->c_value - textsec->vma;
-
- memset (&tbInfo, '\0', sizeof (tbInfo));
-
- /* keep reading blocks of data from the text section, until finding a zero
- word and a traceback table. */
-
- /* Note: The logical thing way to write this code would be to assign
- to bufferbytes within the while condition. But that triggers a
- compiler (xlc in AIX 3.2) bug, so simplify it... */
- bufferbytes =
- (TBTABLE_BUFSIZ < (textsec->_raw_size - functionstart - bytesread) ?
- TBTABLE_BUFSIZ : (textsec->_raw_size - functionstart - bytesread));
- while (bufferbytes
- && (bfd_get_section_contents
- (abfd, textsec, buffer,
- (file_ptr)(functionstart + bytesread), bufferbytes)))
- {
- bytesread += bufferbytes;
- pinsn = (int*) buffer;
-
- /* If this is the first time we filled the buffer, retrieve function
- framesize info. */
-
- if (bytesread == bufferbytes) {
-
- /* skip over unrelated instructions */
-
- if (*pinsn == 0x7c0802a6) /* mflr r0 */
- ++pinsn;
- if ((*pinsn & 0xfc00003e) == 0x7c000026) /* mfcr Rx */
- ++pinsn;
- if ((*pinsn & 0xfc000000) == 0x48000000) /* bl foo, save fprs */
- ++pinsn;
- if ((*pinsn & 0xfc1f0000) == 0xbc010000) /* stm Rx, NUM(r1) */
- ++pinsn;
-
- do {
- int tmp = (*pinsn >> 16) & 0xffff;
-
- if (tmp == 0x9421) { /* stu r1, NUM(r1) */
- tbInfo.framesize = 0x10000 - (*pinsn & 0xffff);
- break;
- }
- else if ((*pinsn == 0x93e1fffc) || /* st r31,-4(r1) */
- (tmp == 0x9001)) /* st r0, NUM(r1) */
- ;
- /* else, could not find a frame size. */
- else
- return NULL;
-
- } while (++pinsn && *pinsn);
-
- if (!tbInfo.framesize)
- return NULL;
-
- }
-
- /* look for a zero word. */
-
- while (*pinsn && (pinsn < (int*)(buffer + bufferbytes - sizeof(int))))
- ++pinsn;
-
- if (pinsn >= (int*)(buffer + bufferbytes))
- continue;
-
- if (*pinsn == 0) {
-
- /* function size is the amount of bytes we have skipped so far. */
- tbInfo.fsize = bytesread - (buffer + bufferbytes - (char*)pinsn);
-
- ++pinsn;
-
- /* if we don't have the whole traceback table in the buffer, re-read
- the whole thing. */
-
- /* This is how much to read to get the traceback table.
- 8 bytes of the traceback table are always present, plus we
- look at parminfo. */
-#define MIN_TBTABSIZ 12
-
- if ((char*)pinsn > (buffer + bufferbytes - MIN_TBTABSIZ)) {
-
- /* In case if we are *very* close to the end of the text section
- and cannot read properly from that point on, abort by returning
- NULL.
-
- This could happen if the traceback table is only 8 bytes,
- but we try to read 12 bytes of it.
- Handle this case more graciously -- FIXME */
-
- if (!bfd_get_section_contents (
- abfd, textsec, buffer,
- (file_ptr)(functionstart +
- bytesread - (buffer + bufferbytes - (char*)pinsn)),MIN_TBTABSIZ))
- { printf_unfiltered ("Abnormal return!..\n"); return NULL; }
-
- ptb = (struct tbtable *)buffer;
- }
- else
- ptb = (struct tbtable *)pinsn;
-
- tbInfo.fixedparms = ptb->tb.fixedparms;
- tbInfo.floatparms = ptb->tb.floatparms;
- tbInfo.parminfo = ptb->tb_ext.parminfo;
- return &tbInfo;
- }
- bufferbytes =
- (TBTABLE_BUFSIZ < (textsec->_raw_size - functionstart - bytesread) ?
- TBTABLE_BUFSIZ : (textsec->_raw_size - functionstart - bytesread));
- }
- return NULL;
-}