📄 xcoffread.c
字号:
of course, but in corresponding .s files.) */ if (inclDepth) fatal ("xcoff internal: pending include file exists."); ++inclDepth; /* allocate an include file, or make room for the new entry */ if (inclLength == 0) { inclTable = (InclTable*) xmalloc (sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); bzero (inclTable, sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); inclLength = INITIAL_INCLUDE_TABLE_LENGTH; inclIndx = 0; } else if (inclIndx >= inclLength) { inclLength += INITIAL_INCLUDE_TABLE_LENGTH; inclTable = (InclTable*) xrealloc (inclTable, sizeof (InclTable) * inclLength); bzero (inclTable+inclLength-INITIAL_INCLUDE_TABLE_LENGTH, sizeof (InclTable)*INITIAL_INCLUDE_TABLE_LENGTH); } inclTable [inclIndx].name = cs->c_name; inclTable [inclIndx].begin = cs->c_value;}static voidrecord_include_end (cs)struct coff_symbol *cs;{ InclTable *pTbl; if (inclDepth == 0) fatal ("xcoff internal: Mismatch C_BINCL/C_EINCL pair found."); pTbl = &inclTable [inclIndx]; pTbl->end = cs->c_value; --inclDepth; ++inclIndx;}/* given the start and end addresses of a compilation unit (or a csect, at times) process its lines and create appropriate line vectors. */static voidprocess_linenos (start, end) CORE_ADDR start, end;{ char *pp; int offset, ii; struct subfile main_subfile; /* subfile structure for the main compilation unit. */ /* in the main source file, any time we see a function entry, we reset this variable to function's absolute starting line number. All the following line numbers in the function are relative to this, and we record absolute line numbers in record_line(). */ int main_source_baseline = 0; unsigned *firstLine; CORE_ADDR addr; if (!(offset = first_fun_line_offset)) goto return_after_cleanup; bzero (&main_subfile, sizeof (main_subfile)); first_fun_line_offset = 0; if (inclIndx == 0) /* All source lines were in the main source file. None in include files. */ enter_line_range (&main_subfile, offset, 0, start, end, &main_source_baseline); /* else, there was source with line numbers in include files */ else { main_source_baseline = 0; for (ii=0; ii < inclIndx; ++ii) { struct subfile *tmpSubfile; /* if there is main file source before include file, enter it. */ if (offset < inclTable[ii].begin) { enter_line_range (&main_subfile, offset, inclTable[ii].begin - LINESZ, start, 0, &main_source_baseline); } /* Have a new subfile for the include file */ tmpSubfile = inclTable[ii].subfile = (struct subfile*) xmalloc (sizeof (struct subfile)); bzero (tmpSubfile, sizeof (struct subfile)); firstLine = &(inclTable[ii].funStartLine); /* enter include file's lines now. */ enter_line_range (tmpSubfile, inclTable[ii].begin, inclTable[ii].end, start, 0, firstLine); offset = inclTable[ii].end + LINESZ; } /* all the include files' line have been processed at this point. Now, enter remaining lines of the main file, if any left. */ if (offset < (linetab_offset + linetab_size + 1 - LINESZ)) { enter_line_range (&main_subfile, offset, 0, start, end, &main_source_baseline); } } /* Process main file's line numbers. */ if (main_subfile.line_vector) { struct linetable *lineTb, *lv; lv = main_subfile.line_vector; /* Line numbers are not necessarily ordered. xlc compilation will put static function to the end. */ lineTb = arrange_linetable (lv); if (lv == lineTb) { current_subfile->line_vector = (struct linetable *) xrealloc (lv, (sizeof (struct linetable) + lv->nitems * sizeof (struct linetable_entry))); } else { free (lv); current_subfile->line_vector = lineTb; } current_subfile->line_vector_length = current_subfile->line_vector->nitems; } /* Now, process included files' line numbers. */ for (ii=0; ii < inclIndx; ++ii) { if ( (inclTable[ii].subfile)->line_vector) { /* Useless if!!! FIXMEmgo */ struct linetable *lineTb, *lv; lv = (inclTable[ii].subfile)->line_vector; /* Line numbers are not necessarily ordered. xlc compilation will put static function to the end. */ lineTb = arrange_linetable (lv); push_subfile (); /* For the same include file, we might want to have more than one subfile. This happens if we have something like: ...... #include "foo.h" ...... #include "foo.h" ...... while foo.h including code in it. (stupid but possible) Since start_subfile() looks at the name and uses an existing one if finds, we need to provide a fake name and fool it. *//* start_subfile (inclTable[ii].name, (char*)0); */ start_subfile (" ?", (char*)0); current_subfile->name = obsavestring (inclTable[ii].name, strlen (inclTable[ii].name), ¤t_objfile->symbol_obstack); if (lv == lineTb) { current_subfile->line_vector = (struct linetable *) xrealloc (lv, (sizeof (struct linetable) + lv->nitems * sizeof (struct linetable_entry))); } else { free (lv); current_subfile->line_vector = lineTb; } current_subfile->line_vector_length = current_subfile->line_vector->nitems; start_subfile (pop_subfile (), (char*)0); } }return_after_cleanup: /* We don't want to keep alloc/free'ing the global include file table. */ inclIndx = 0; /* start with a fresh subfile structure for the next file. */ bzero (&main_subfile, sizeof (struct subfile));}voidaix_process_linenos (){ /* process line numbers and enter them into line vector */ process_linenos (last_source_start_addr, cur_src_end_addr);}/* Enter a given range of lines into the line vector. can be called in the following two ways: enter_line_range (subfile, beginoffset, endoffset, startaddr, 0, firstLine) or enter_line_range (subfile, beginoffset, 0, startaddr, endaddr, firstLine) */static voidenter_line_range (subfile, beginoffset, endoffset, startaddr, endaddr, firstLine) struct subfile *subfile; unsigned beginoffset, endoffset; /* offsets to line table */ CORE_ADDR startaddr, endaddr; unsigned *firstLine;{ char *pp, *limit; CORE_ADDR addr;/* Do Byte swapping, if needed. FIXME! */#define P_LINENO(PP) (*(unsigned short*)((struct external_lineno*)(PP))->l_lnno)#define P_LINEADDR(PP) (*(long*)((struct external_lineno*)(PP))->l_addr.l_paddr)#define P_LINESYM(PP) (*(long*)((struct external_lineno*)(PP))->l_addr.l_symndx) pp = &linetab [beginoffset - linetab_offset]; limit = endoffset ? &linetab [endoffset - linetab_offset] : &linetab [linetab_size -1]; while (pp <= limit) { /* find the address this line represents */ addr = P_LINENO(pp) ? P_LINEADDR(pp) : read_symbol_nvalue (symtbl, P_LINESYM(pp)); if (addr < startaddr || (endaddr && addr > endaddr)) return; if (P_LINENO(pp) == 0) { *firstLine = read_symbol_lineno (symtbl, P_LINESYM(pp)); record_line (subfile, 0, addr); --(*firstLine); } else record_line (subfile, *firstLine + P_LINENO(pp), addr); pp += LINESZ; }}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;/* Given a function symbol, return its traceback information. */ TracebackInfo *retrieve_tracebackinfo (abfd, textsec, cs) bfd *abfd; sec_ptr textsec; struct coff_symbol *cs;{#define TBTABLE_BUFSIZ 2000#define MIN_TBTABSIZ 50 /* minimum buffer size to hold a traceback table. */ 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 = cs->c_value - textsec->vma; bzero (&tbInfo, sizeof (tbInfo)); /* keep reading blocks of data from the text section, until finding a zero word and a traceback table. */ while ( bufferbytes = ( (TBTABLE_BUFSIZ < (textsec->_raw_size - functionstart - bytesread)) ? TBTABLE_BUFSIZ : (textsec->_raw_size - functionstart - bytesread)) && 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. */ 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. 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 ("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; } } return NULL;}#if 0/* Given a function symbol, return a pointer to its traceback table. */ struct tbtable *retrieve_traceback (abfd, textsec, cs, size) bfd *abfd; sec_ptr textsec; struct coff_symbol *cs; int *size; /* return function size */{#define TBTABLE_BUFSIZ 2000#define MIN_TBTABSIZ 50 /* minimum buffer size to hold a traceback table. */ 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 = cs->c_value - textsec->filepos + textsec->vma; *size = 0; /* keep reading blocks of data from the text section, until finding a zero word and a traceback table. */ while (bfd_get_section_contents (abfd, textsec, buffer, (file_ptr)(functionstart + bytesread), bufferbytes = ( (TBTABLE_BUFSIZ < (textsec->size - functionstart - bytesread)) ? TBTABLE_BUFSIZ : (textsec->size - functionstart - bytesread)))) { bytesread += bufferbytes; pinsn = (int*) buffer; /* 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. */ *size = bytesread - (buffer + bufferbytes - pinsn); ++pinsn; /* if we don't have the whole traceback table in the buffer, re-read the whole thing. */ 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 for now. Handle this case more graciously -- FIXME */ if (!bfd_get_section_contents ( abfd, textsec, buffer, (file_ptr)(functionstart + bytesread - (buffer + bufferbytes - pinsn)),MIN_TBTABSIZ)) /* abort (); */ { printf ("abort!!!\n"); return NULL; } return (struct tbtable *)buffer; } else return (struct tbtable *)pinsn; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -