diff options
Diffstat (limited to 'contrib/binutils/gas/listing.c')
-rw-r--r-- | contrib/binutils/gas/listing.c | 352 |
1 files changed, 234 insertions, 118 deletions
diff --git a/contrib/binutils/gas/listing.c b/contrib/binutils/gas/listing.c index f0c2295..2fa8ae9 100644 --- a/contrib/binutils/gas/listing.c +++ b/contrib/binutils/gas/listing.c @@ -1,5 +1,6 @@ /* listing.c - mainting assembly listings - Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. + Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -100,6 +101,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "subsegs.h" #ifndef NO_LISTING + #ifndef LISTING_HEADER #define LISTING_HEADER "GAS LISTING" #endif @@ -119,45 +121,42 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define LISTING_LHS_CONT_LINES 4 #endif - - - /* This structure remembers which .s were used */ typedef struct file_info_struct { - char *filename; - int linenum; - FILE *file; struct file_info_struct *next; + char *filename; + long pos; + unsigned int linenum; int at_end; } - file_info_type; /* this structure rememebrs which line from which file goes into which frag */ -typedef struct list_info_struct +struct list_info_struct { /* Frag which this line of source is nearest to */ fragS *frag; + /* The actual line in the source file */ unsigned int line; /* Pointer to the file info struct for the file which this line belongs to */ file_info_type *file; + /* The expanded text of any macro that may have been executing. */ + char *line_contents; + /* Next in list */ struct list_info_struct *next; - /* Pointer to the file info struct for the high level language source line that belongs here */ file_info_type *hll_file; - /* High level language source line */ - int hll_line; - + unsigned int hll_line; /* Pointer to any error message associated with this line */ char *message; @@ -174,10 +173,13 @@ typedef struct list_info_struct } edict; char *edict_arg; -} - -list_info_type; + /* Nonzero if this line is to be omitted because it contains + debugging information. This can become a flags field if we come + up with more information to store here. */ + int debugging; +}; +typedef struct list_info_struct list_info_type; static struct list_info_struct *head; struct list_info_struct *listing_tail; @@ -189,15 +191,16 @@ static int paper_height = 60; /* File to output listings to. */ static FILE *list_file; -/* this static array is used to keep the text of data to be printed - before the start of the line. - It is stored so we can give a bit more info on the next line. To much, and large - initialized arrays will use up lots of paper. - */ +/* This static array is used to keep the text of data to be printed + before the start of the line. */ -static char data_buffer[100]; -static unsigned int data_buffer_size; +#define MAX_BYTES \ + (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width \ + + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second) \ + * listing_lhs_cont_lines) \ + + 20) +static char *data_buffer; /* Prototypes. */ static void listing_message PARAMS ((const char *name, const char *message)); @@ -214,7 +217,7 @@ static void print_source PARAMS ((file_info_type *current_file, list_info_type *list, char *buffer, unsigned int width)); -static int debugging_pseudo PARAMS ((char *line)); +static int debugging_pseudo PARAMS ((list_info_type *, const char *)); static void listing_listing PARAMS ((char *name)); @@ -248,9 +251,15 @@ listing_error (message) } +int listing_lhs_width = LISTING_LHS_WIDTH; +int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND; +int listing_lhs_cont_lines = LISTING_LHS_CONT_LINES; +int listing_rhs_width = LISTING_RHS_WIDTH; static file_info_type *file_info_head; +static file_info_type *last_open_file_info; +static FILE *last_open_file; static file_info_type * file_info (file_name) @@ -273,13 +282,10 @@ file_info (file_name) file_info_head = p; p->filename = xmalloc ((unsigned long) strlen (file_name) + 1); strcpy (p->filename, file_name); + p->pos = 0; p->linenum = 0; p->at_end = 0; - p->file = fopen (p->filename, "r"); - if (p->file) - fgetc (p->file); - return p; } @@ -301,7 +307,7 @@ listing_newline (ps) unsigned int line; static unsigned int last_line = 0xffff; static char *last_file = NULL; - list_info_type *new; + list_info_type *new = NULL; if (listing == 0) return; @@ -309,34 +315,77 @@ listing_newline (ps) if (now_seg == absolute_section) return; +#ifdef OBJ_ELF + /* In ELF, anything in a section beginning with .debug or .line is + considered to be debugging information. This includes the + statement which switches us into the debugging section, which we + can only set after we are already in the debugging section. */ + if ((listing & LISTING_NODEBUG) != 0 + && listing_tail != NULL + && ! listing_tail->debugging) + { + const char *segname; + + segname = segment_name (now_seg); + if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (segname, ".line", sizeof ".line" - 1) == 0) + listing_tail->debugging = 1; + } +#endif + as_where (&file, &line); - if (line != last_line || (last_file && file && strcmp(file, last_file))) + if (ps == NULL) { - last_line = line; - last_file = file; - new_frag (); + if (line == last_line && !(last_file && file && strcmp(file, last_file))) + return; new = (list_info_type *) xmalloc (sizeof (list_info_type)); - new->frag = frag_now; - new->line = line; - new->file = file_info (file); + new->line_contents = NULL; + } + else + { + new = (list_info_type *) xmalloc (sizeof (list_info_type)); + new->line_contents = ps; + } - if (listing_tail) - { - listing_tail->next = new; - } - else - { - head = new; - } - listing_tail = new; - new->next = (list_info_type *) NULL; - new->message = (char *) NULL; - new->edict = EDICT_NONE; - new->hll_file = (file_info_type *) NULL; - new->hll_line = 0; - new_frag (); + last_line = line; + last_file = file; + new_frag (); + + if (listing_tail) + { + listing_tail->next = new; + } + else + { + head = new; } + listing_tail = new; + + new->frag = frag_now; + new->line = line; + new->file = file_info (file); + new->next = (list_info_type *) NULL; + new->message = (char *) NULL; + new->edict = EDICT_NONE; + new->hll_file = (file_info_type *) NULL; + new->hll_line = 0; + new->debugging = 0; + new_frag (); + +#ifdef OBJ_ELF + /* In ELF, anything in a section beginning with .debug or .line is + considered to be debugging information. */ + if ((listing & LISTING_NODEBUG) != 0) + { + const char *segname; + + segname = segment_name (now_seg); + if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (segname, ".line", sizeof ".line" - 1) == 0) + new->debugging = 1; + } +#endif } /* Attach all current frags to the previous line instead of the @@ -386,15 +435,32 @@ buffer_line (file, line, size) char *p = line; /* If we couldn't open the file, return an empty line */ - if (file->file == (FILE *) NULL || file->at_end) + if (file->at_end) + return ""; + + /* Check the cache and see if we last used this file. */ + if (!last_open_file_info || file != last_open_file_info) { - return ""; - } + if (last_open_file) + { + last_open_file_info->pos = ftell (last_open_file); + fclose (last_open_file); + } - if (file->linenum == 0) - rewind (file->file); + last_open_file_info = file; + last_open_file = fopen (file->filename, "r"); + if (last_open_file == NULL) + { + file->at_end = 1; + return ""; + } - c = fgetc (file->file); + /* Seek to where we were last time this file was open. */ + if (file->pos) + fseek(last_open_file, file->pos, SEEK_SET); + } + + c = fgetc (last_open_file); size -= 1; /* leave room for null */ @@ -404,7 +470,7 @@ buffer_line (file, line, size) *p++ = c; count++; - c = fgetc (file->file); + c = fgetc (last_open_file); } if (c == EOF) @@ -435,7 +501,7 @@ listing_page (list) { /* Grope around, see if we can see a title or subtitle edict coming up soon (we look down 10 lines of the page and see if it's there)*/ - if ((eject || (on_page >= paper_height)) && paper_height != 0) + if ((eject || (on_page >= (unsigned int) paper_height)) && paper_height != 0) { unsigned int c = 10; int had_title = 0; @@ -478,15 +544,13 @@ static unsigned int calc_hex (list) list_info_type * list; { + int data_buffer_size; list_info_type *first = list; - unsigned int address = (unsigned int) ~0; - + unsigned int address = ~ (unsigned int) 0; fragS *frag; fragS *frag_ptr; - unsigned int byte_in_frag; - /* Find first frag which says it belongs to this line */ frag = list->frag; while (frag && frag->line != list) @@ -501,9 +565,10 @@ calc_hex (list) { /* Print as many bytes from the fixed part as is sensible */ byte_in_frag = 0; - while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10) + while ((offsetT) byte_in_frag < frag_ptr->fr_fix + && data_buffer_size < MAX_BYTES - 3) { - if (address == ~0) + if (address == ~ (unsigned int) 0) { address = frag_ptr->fr_address; } @@ -519,11 +584,11 @@ calc_hex (list) unsigned int var_rep_idx = byte_in_frag; /* Print as many bytes from the variable part as is sensible */ - while ((byte_in_frag + while (((offsetT) byte_in_frag < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset) - && data_buffer_size < sizeof (data_buffer) - 10) + && data_buffer_size < MAX_BYTES - 3) { - if (address == ~0) + if (address == ~ (unsigned int) 0) { address = frag_ptr->fr_address; } @@ -539,14 +604,14 @@ calc_hex (list) var_rep_idx++; byte_in_frag++; - if (var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var) + if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var) var_rep_idx = var_rep_max; } } frag_ptr = frag_ptr->fr_next; } - data_buffer[data_buffer_size++] = 0; + data_buffer[data_buffer_size] = '\0'; return address; } @@ -570,9 +635,9 @@ print_lines (list, lineno, string, address) /* Print the stuff on the first line */ listing_page (list); - nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH; + nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width; /* Print the hex for the first line */ - if (address == ~0) + if (address == ~ (unsigned int) 0) { fprintf (list_file, "% 4d ", lineno); for (idx = 0; idx < nchars; idx++) @@ -625,11 +690,11 @@ print_lines (list, lineno, string, address) } for (lines = 0; - lines < LISTING_LHS_CONT_LINES - && *src; + lines < (unsigned int) listing_lhs_cont_lines && *src; lines++) { - nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1; + nchars = (((LISTING_WORD_SIZE * 2) + 1) + * listing_lhs_width_second - 1); idx = 0; /* Print any more lines of data, but more compactly */ fprintf (list_file, "% 4d ", lineno); @@ -671,8 +736,14 @@ list_symbol_table () for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr)) { - if (ptr->sy_frag->line) + if (SEG_NORMAL (S_GET_SEGMENT (ptr)) + || S_GET_SEGMENT (ptr) == absolute_section) { +#ifdef BFD_ASSEMBLER + /* Don't report section symbols. They are not interesting. */ + if (ptr->bsym->flags & BSF_SECTION_SYM) + continue; +#endif if (S_GET_NAME (ptr)) { char buf[30], fmt[8]; @@ -702,11 +773,20 @@ list_symbol_table () got_some = 1; } - fprintf (list_file, "%20s:%-5d %s:%s %s\n", - ptr->sy_frag->line->file->filename, - ptr->sy_frag->line->line, - segment_name (S_GET_SEGMENT (ptr)), - buf, S_GET_NAME (ptr)); + if (ptr->sy_frag && ptr->sy_frag->line) + { + fprintf (list_file, "%20s:%-5d %s:%s %s\n", + ptr->sy_frag->line->file->filename, + ptr->sy_frag->line->line, + segment_name (S_GET_SEGMENT (ptr)), + buf, S_GET_NAME (ptr)); + } + else + { + fprintf (list_file, "%33s:%s %s\n", + segment_name (S_GET_SEGMENT (ptr)), + buf, S_GET_NAME (ptr)); + } on_page++; listing_page (0); @@ -729,11 +809,7 @@ list_symbol_table () { if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0) { - if (ptr->sy_frag->line == 0 -#ifdef S_IS_REGISTER - && !S_IS_REGISTER (ptr) -#endif - && S_GET_SEGMENT (ptr) != reg_section) + if (S_GET_SEGMENT (ptr) == undefined_section) { if (!got_some) { @@ -763,13 +839,13 @@ print_source (current_file, list, buffer, width) char *buffer; unsigned int width; { - if (current_file->file) + if (!current_file->at_end) { while (current_file->linenum < list->hll_line && !current_file->at_end) { char *p = buffer_line (current_file, buffer, width); - fprintf (list_file, "%4d:%-13s **** %s\n", current_file->linenum, + fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum, current_file->filename, p); on_page++; listing_page (list); @@ -778,17 +854,48 @@ print_source (current_file, list, buffer, width) } /* Sometimes the user doesn't want to be bothered by the debugging - records inserted by the compiler, see if the line is suspicious */ + records inserted by the compiler, see if the line is suspicious. */ static int -debugging_pseudo (line) - char *line; +debugging_pseudo (list, line) + list_info_type *list; + const char *line; { - while (isspace (*line)) + static int in_debug; + int was_debug; + + if (list->debugging) + { + in_debug = 1; + return 1; + } + + was_debug = in_debug; + in_debug = 0; + + while (isspace ((unsigned char) *line)) line++; if (*line != '.') - return 0; + { +#ifdef OBJ_ELF + /* The ELF compiler sometimes emits blank lines after switching + out of a debugging section. If the next line drops us back + into debugging information, then don't print the blank line. + This is a hack for a particular compiler behaviour, not a + general case. */ + if (was_debug + && *line == '\0' + && list->next != NULL + && list->next->debugging) + { + in_debug = 1; + return 1; + } +#endif + + return 0; + } line++; @@ -819,7 +926,6 @@ debugging_pseudo (line) return 1; return 0; - } static void @@ -834,7 +940,8 @@ listing_listing (name) int show_listing = 1; unsigned int width; - buffer = xmalloc (LISTING_RHS_WIDTH); + buffer = xmalloc (listing_rhs_width); + data_buffer = xmalloc (MAX_BYTES); eject = 1; list = head; @@ -851,8 +958,8 @@ listing_listing (name) while (list) { - width = LISTING_RHS_WIDTH > paper_width ? paper_width : - LISTING_RHS_WIDTH; + width = listing_rhs_width > paper_width ? paper_width : + listing_rhs_width; switch (list->edict) { @@ -889,26 +996,38 @@ listing_listing (name) current_hll_file = list->hll_file; } - if (current_hll_file && list->hll_line && listing & LISTING_HLL) + if (current_hll_file && list->hll_line && (listing & LISTING_HLL)) { print_source (current_hll_file, list, buffer, width); } - while (list->file->file - && list->file->linenum < list->line - && !list->file->at_end) + if (list->line_contents) { - unsigned int address; + if (!((listing & LISTING_NODEBUG) + && debugging_pseudo (list, list->line_contents))) + { + print_lines (list, list->file->linenum, + list->line_contents, calc_hex (list)); + } + } + else + { + while (list->file->linenum < list->line + && !list->file->at_end) + { + unsigned int address; - p = buffer_line (list->file, buffer, width); + p = buffer_line (list->file, buffer, width); - if (list->file->linenum < list->line) - address = ~ (unsigned int) 0; - else - address = calc_hex (list); + if (list->file->linenum < list->line) + address = ~ (unsigned int) 0; + else + address = calc_hex (list); - if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p))) - print_lines (list, list->file->linenum, p, address); + if (!((listing & LISTING_NODEBUG) + && debugging_pseudo (list, p))) + print_lines (list, list->file->linenum, p, address); + } } if (list->edict == EDICT_EJECT) @@ -918,8 +1037,7 @@ listing_listing (name) } else { - while (list->file->file - && list->file->linenum < list->line + while (list->file->linenum < list->line && !list->file->at_end) p = buffer_line (list->file, buffer, width); } @@ -929,7 +1047,10 @@ listing_listing (name) list = list->next; } + free (buffer); + free (data_buffer); + data_buffer = NULL; } void @@ -937,7 +1058,6 @@ listing_print (name) char *name; { int using_stdout; - file_info_type *fi; title = ""; subtitle = ""; @@ -981,13 +1101,9 @@ listing_print (name) as_perror ("error closing list file: %s", name); } - for (fi = file_info_head; fi != NULL; fi = fi->next) + if (last_open_file) { - if (fi->file != NULL) - { - fclose (fi->file); - fi->file = NULL; - } + fclose (last_open_file); } } |