Made multiple sections with subsections work.
authorSteve Chamberlain <sac@cygnus>
Thu, 28 Nov 1991 21:22:41 +0000 (21:22 +0000)
committerSteve Chamberlain <sac@cygnus>
Thu, 28 Nov 1991 21:22:41 +0000 (21:22 +0000)
gas/config/obj-coff-bfd.c

index 494d2c69a264088b227f63d2cc83a59b5b30f9ad..d2e24e1ea29f0e2286570f65dcc8ea7b97ebf6b1 100755 (executable)
@@ -1,5 +1,4 @@
-
-/* coff object file format
+/* coff object file format with bfd
    Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
 
 This file is part of GAS.
@@ -23,15 +22,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  How does this releate to the rest of GAS ?
 
  Well, all the other files in gas are more or less a black box. It
- takes care of openning files, parsing command lines, stripping blanks
+ takes care of opening files, parsing command lines, stripping blanks
  etc etc. This module gets a chance to register what it wants to do by
  saying that it is interested in various pseduo ops. The other big
  change is write_object_file. This runs through all the data
  structures that gas builds, and outputs the file in the format of our
  choice.
  
-
  Hacked for BFDness by steve chamberlain
+
+ Note that this is the first implementation using BFD for coff, and
+ this is a pretty special case too - it only works at the moment for
+ the H8. Which *can't* do any relaxing during assembly - because the
+ linker has to have all the reloc info for fancy stuff later on.
+
+ When another machine is supported, relaxing will have to go back in.
+
  sac@cygnus.com
 */
 
@@ -42,11 +48,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
 
-
-
 /* This vector is used to turn an internal segment into a section #
    suitable for insertion into a coff symbol table 
-*/
+ */
 
 const short seg_N_TYPE[] = { /* in: segT   out: N_TYPE bits */
        C_ABS_SECTION,
@@ -72,6 +76,7 @@ const short seg_N_TYPE[] = { /* in: segT   out: N_TYPE bits */
        C_REGISTER_SECTION,     /* SEG_REGISTER */
 };
 
+
 int function_lineoff = -1;     /* Offset in line#s where the last function
                                   started (the odd entry for line #0) */
 
@@ -241,7 +246,7 @@ static unsigned int  DEFUN(size_section,(abfd, idx),
 {
   asection *sec;
   unsigned int size = 0;
-  fragS *frag = segment_info[idx].frag_root;
+  fragS *frag = segment_info[idx].frchainP->frch_root;
   while (frag) {
       if (frag->fr_address != size) {  
          printf("Out of step\n");
@@ -366,7 +371,7 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
       struct internal_scnhdr *s = &( segment_info[i].scnhdr);
          
       if (s->s_name[0]) {
-         fragS *frag = segment_info[i].frag_root;
+         fragS *frag = segment_info[i].frchainP->frch_root;
          char *buffer =  alloca(s->s_size);
          s->s_scnptr = *file_cursor;
          s->s_paddr =  paddr;
@@ -1400,157 +1405,6 @@ char *where;
 }
 
 
-#if 0
-void obj_pre_write_hook(headers)
-object_headers *headers;
-{
-  register fixS *fixP;
-
-  /* FIXME-SOMEDAY this should be done at
-     fixup_segment time but I'm going to wait until I
-     do multiple segments.  xoxorich. */
-  unsigned int i;
-  unsigned int reloc_size = 0;
-  
-  for (i =0; i < N_SEG; i++) 
-  {
-    seg_info_type *s = &(SEG_INFO_FROM_SEG_NUMBER(i));
-    
-    if (s->real_section) 
-    {
-
-      for (fixP = s->fix_root; fixP; fixP = fixP->fx_next) {
-         if (fixP->fx_addsy) {
-             s->relocation_number++;
-           }   
-       }       
-
-    }
-    headers->relocation_size += s->relocation_number * RELSZ;    
-  }
-  
-  /* filehdr */
-  H_SET_FILE_MAGIC_NUMBER(headers, FILE_HEADER_MAGIC);
-  H_SET_NUMBER_OF_SECTIONS(headers, 3); /* text+data+bss */
-#ifndef OBJ_COFF_OMIT_TIMESTAMP
-  H_SET_TIME_STAMP(headers, (long)time((long*)0));
-#else                          /* OBJ_COFF_OMIT_TIMESTAMP */
-  H_SET_TIME_STAMP(headers, 0);
-#endif                         /* OBJ_COFF_OMIT_TIMESTAMP */
-  H_SET_SYMBOL_TABLE_POINTER(headers, H_GET_SYMBOL_TABLE_FILE_OFFSET(headers));
-#if 0
-  printf("FILHSZ %x\n", FILHSZ);
-  printf("OBJ_COFF_AOUTHDRSZ %x\n", OBJ_COFF_AOUTHDRSZ);
-  printf("section headers %x\n", H_GET_NUMBER_OF_SECTIONS(headers)  * SCNHSZ);
-  printf("get text size %x\n", H_GET_TEXT_SIZE(headers));
-  printf("get data size %x\n", H_GET_DATA_SIZE(headers));
-  printf("get relocation size %x\n", H_GET_RELOCATION_SIZE(headers));
-  printf("get lineno size %x\n", H_GET_LINENO_SIZE(headers));
-#endif
-  /* symbol table size allready set */
-  H_SET_SIZEOF_OPTIONAL_HEADER(headers, OBJ_COFF_AOUTHDRSZ);
-  H_SET_FLAGS(headers, (text_lineno_number == 0 ? F_LNNO : 0)
-             | headers->relocation_size ? F_RELFLG : 0
-             | BYTE_ORDERING);
-
-  /* aouthdr */
-  /* magic number allready set */
-  H_SET_VERSION_STAMP(headers, 0);
-
-}                              /* obj_pre_write_hook() */
-#endif
-/* This is a copy from aout.  All I do is neglect to actually build the symbol. */
-
-static void obj_coff_stab(what)
-int what;
-{
-       char *string;
-       expressionS e;
-       int goof = 0;   /* TRUE if we have aborted. */
-       int length;
-       int saved_type = 0;
-       long longint;
-       symbolS *symbolP = 0;
-
-       if (what == 's') {
-               string = demand_copy_C_string(&length);
-               SKIP_WHITESPACE();
-
-               if (*input_line_pointer == ',') {
-                       input_line_pointer++;
-               } else {
-                       as_bad("I need a comma after symbol's name");
-                       goof = 1;
-               } /* better be a comma */
-       } /* skip the string */
-
-       /*
-        * Input_line_pointer->after ','.  String->symbol name.
-        */
-       if (!goof) {
-               if (get_absolute_expression_and_terminator(&longint) != ',') {
-                       as_bad("I want a comma after the n_type expression");
-                       goof = 1;
-                       input_line_pointer--; /* Backup over a non-',' char. */
-               } /* on error */
-       } /* no error */
-
-       if (!goof) {
-               if (get_absolute_expression_and_terminator(&longint) != ',') {
-                       as_bad("I want a comma after the n_other expression");
-                       goof = 1;
-                       input_line_pointer--; /* Backup over a non-',' char. */
-               } /* on error */
-       } /* no error */
-
-       if (!goof) {
-               get_absolute_expression();
-
-               if (what == 's' || what == 'n') {
-                       if (*input_line_pointer != ',') {
-                               as_bad("I want a comma after the n_desc expression");
-                               goof = 1;
-                       } else {
-                               input_line_pointer++;
-                       } /* on goof */
-               } /* not stabd */
-       } /* no error */
-
-       expression(&e);
-
-       if (goof) {
-               ignore_rest_of_line();
-       } else {
-               demand_empty_rest_of_line();
-       } /* on error */
-} /* obj_coff_stab() */
-
-#ifdef DEBUG
- /* for debugging */
-char *s_get_name(s)
-symbolS *s;
-{
-       return((s == NULL) ? "(NULL)" : S_GET_NAME(s));
-} /* s_get_name() */
-
-void symbol_dump() {
-       symbolS *symbolP;
-
-       for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
-               printf("%3ld: 0x%lx \"%s\" type = %ld, class = %d, segment = %d\n",
-                      symbolP->sy_number,
-                      (unsigned long) symbolP,
-                      S_GET_NAME(symbolP),
-                      (long) S_GET_DATA_TYPE(symbolP),
-                      S_GET_STORAGE_CLASS(symbolP),
-                      (int) S_GET_SEGMENT(symbolP));
-       } /* traverse symbols */
-
-       return;
-} /* symbol_dump() */
-#endif /* DEBUG */
-
-
 
 static void 
 DEFUN(do_linenos_for,(abfd, file_cursor),
@@ -1605,109 +1459,110 @@ DEFUN(do_linenos_for,(abfd, file_cursor),
  */
 
 /* end of obj-coff.c */
+/* Now we run through the list of frag chains in a segment and
+   make all the subsegment frags appear at the end of the
+   list, as if the seg 0 was extra long */
 
+static void DEFUN_VOID(remove_subsegs)
+{
+    unsigned int i;            
+
+    for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+    { 
+       frchainS *head =  segment_info[i].frchainP;
+       fragS dummy;
+       fragS * prev_frag = &dummy;
+       
+       while (head && head->frch_seg == i) 
+       {
+           prev_frag->fr_next = head->frch_root;
+           prev_frag = head->frch_last;
+           head = head->frch_next;
+       }
+       prev_frag->fr_next = 0;
+    }
+}
 
 
 extern void DEFUN_VOID(write_object_file)
 {
-  int i;
-  struct frchain *frchain_ptr; 
-  struct frag *frag_ptr;
-  struct internal_filehdr filehdr;
-  struct internal_aouthdr aouthdr;
-unsigned long file_cursor;  
-  bfd *abfd;
+    int i;
+    struct frchain *frchain_ptr; 
+    struct frag *frag_ptr;
+    struct internal_filehdr filehdr;
+    struct internal_aouthdr aouthdr;
+    unsigned long file_cursor;  
+    bfd *abfd;
   
-  abfd = bfd_openw(out_file_name, TARGET_FORMAT);
+    abfd = bfd_openw(out_file_name, TARGET_FORMAT);
 
-  if (abfd == 0) {
-      as_perror ("FATAL: Can't create %s", out_file_name);
-      exit(42);
-    }
-  bfd_set_format(abfd, bfd_object);
-  bfd_set_arch_mach(abfd, bfd_arch_h8300, 0);
+    if (abfd == 0) {
+           as_perror ("FATAL: Can't create %s", out_file_name);
+           exit(42);
+       }
+    bfd_set_format(abfd, bfd_object);
+    bfd_set_arch_mach(abfd, bfd_arch_h8300, 0);
 
 
-  string_byte_count = 4;
+    string_byte_count = 4;
   
-  for (frchain_ptr = frchain_root;
-       frchain_ptr != (struct frchain *)NULL; 
-       frchain_ptr = frchain_ptr->frch_next) {
-      /* Run through all the sub-segments and align them up. Also close any
-        open frags. We tack a .fill onto the end of the frag chain so
-        that any .align's size can be worked by looking at the next
-        frag */
-
-      subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
-#define SUB_SEGMENT_ALIGN 2
-      frag_align(SUB_SEGMENT_ALIGN,0);
-      frag_wane(frag_now);
-      frag_now->fr_fix = 0;
-      know( frag_now->fr_next == NULL );
-    }
+    for (frchain_ptr = frchain_root;
+        frchain_ptr != (struct frchain *)NULL; 
+        frchain_ptr = frchain_ptr->frch_next) {
+           /* Run through all the sub-segments and align them up. Also close any
+              open frags. We tack a .fill onto the end of the frag chain so
+              that any .align's size can be worked by looking at the next
+              frag */
+
+           subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#define SUB_SEGMENT_ALIGN 1
+           frag_align(SUB_SEGMENT_ALIGN,0);
+           frag_wane(frag_now);
+           frag_now->fr_fix = 0;
+           know( frag_now->fr_next == NULL );
+       }
 
-  /* Now build one big frag chain for each segment, linked through
-     fr_next. */
-  for (i = SEG_E0; i < SEG_UNKNOWN; i++)
-  { 
-      
-    fragS ** prev_frag_ptr_ptr ;
-    struct frchain *next_frchain_ptr;
-  
-    /* struct frag **head_ptr = segment_info[i].frag_root;*/
 
-    segment_info[i].frag_root =  segment_info[i].frchainP->frch_root;
-#if 0
-    /* Im not sure what this is for */
-    for (frchain_ptr = segment_info[i].frchainP->frch_root;
-        frchain_ptr != (struct frchain *)NULL;
-        frchain_ptr = frchain_ptr->frch_next)
-    {
-      *head_ptr = frchain_ptr;
-      head_ptr = &frchain_ptr->next;
-    }
-     
-
-#endif
-  }
+    remove_subsegs();
+    
 #if 1
-  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
-  {
-      relax_segment(segment_info[i].frag_root, i);
+    for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+    {
+       relax_segment(segment_info[i].frchainP->frch_root, i);
     }
   
-  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
-  {
-/*      fixup_segment(segment_info[i].fix_root, i);*/
-   }
+    for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+    {
+       /*      fixup_segment(segment_info[i].fix_root, i);*/
+    }
   
 #endif
 
-{
-  unsigned int addr = 0;
-  filehdr.f_nscns = 0;
-  
-  /* Find out how big the sections are */
-  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
   {
+      unsigned int addr = 0;
+      filehdr.f_nscns = 0;
+  
+      /* Find out how big the sections are */
+      for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+      {
 
-    if (segment_info[i].scnhdr.s_name[0]) 
-    {
-      filehdr.f_nscns++;
-    }
-    segment_info[i].scnhdr.s_paddr = addr;
-    if (i == SEG_E2) {
-       /* THis is a special case, we leave the size alone, which will have */
-       /* been made up from all and any lcomms seen */
+         if (segment_info[i].scnhdr.s_name[0]) 
+         {
+             filehdr.f_nscns++;
+         }
+         segment_info[i].scnhdr.s_paddr = addr;
+         if (i == SEG_E2) {
+                 /* THis is a special case, we leave the size alone, which will have */
+                 /* been made up from all and any lcomms seen */
 
-      }
-    else {
-       addr += size_section(abfd, i);
+             }
+         else {
+                 addr += size_section(abfd, i);
+             }
       }
   }
-}
 
-  /* Turn the gas native symbol table shape into a coff symbol table */
+    /* Turn the gas native symbol table shape into a coff symbol table */
   crawl_symbols(&filehdr, abfd);
 
   file_cursor =   FILHSZ + SCNHSZ * filehdr.f_nscns ;
@@ -1748,9 +1603,10 @@ unsigned long file_cursor;
 }
 
 
-static void DEFUN(change_to_section,(name, len),
+static void DEFUN(change_to_section,(name, len, exp),
  char *name AND
- unsigned int len)
+ unsigned int len AND
+ unsigned int exp)
 {
   unsigned int i;  
   /* Find out if we've already got a section of this name etc */
@@ -1758,47 +1614,63 @@ static void DEFUN(change_to_section,(name, len),
   {
     if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0) 
     {
-      subseg_new(i, 0);  
+      subseg_new(i, exp);  
       return;
       
     }
   }
   /* No section, add one */
   strncpy(segment_info[i].scnhdr.s_name, name, 8);
-  subseg_new(i, 0);  
+  subseg_new(i, exp);  
 }
 
 static void 
 DEFUN_VOID(obj_coff_section)
 {
-  /* Strip out the section name */
-  char *section_name ;
-  char *section_name_end;
-  
-  unsigned int len;
-
-  section_name =  input_line_pointer;
-  get_symbol_end();
-  section_name_end =  input_line_pointer;
-  input_line_pointer++;
+    /* Strip out the section name */
+    char *section_name ;
+    char *section_name_end;
+    char c;
+    
+    unsigned int len;
+    unsigned int exp;
   
-  len = section_name_end - section_name ;
+    section_name =  input_line_pointer;
+    c =   get_symbol_end();
+    section_name_end =  input_line_pointer;
+
+    len = section_name_end - section_name ;
+    input_line_pointer++;
+    SKIP_WHITESPACE();
+    if (c == ',')
+    {
+       exp = get_absolute_expression();
+    }
+    else if ( *input_line_pointer == ',') 
+    {
+    
+       input_line_pointer++;
+       exp = get_absolute_expression();    
+    }
+    else 
+    {
+       exp = 0;
+    }
   
-
-  change_to_section(section_name, len);
+    change_to_section(section_name, len,exp);
   
 }
 
 
 static void obj_coff_text()
 {
-  change_to_section(".text",5);
+  change_to_section(".text",5, get_absolute_expression());
 }
 
 
 static void obj_coff_data()
 {
-  change_to_section(".data",5);
+  change_to_section(".data",5, get_absolute_expression());
 }
 
 void c_symbol_merge(debug, normal)
@@ -2146,39 +2018,37 @@ segT            this_segment_type; /* N_TYPE bits for segment. */
 
 void obj_coff_lcomm(void)
 {
-       char *name;
-       char c;
-       int temp;
-       char *p;
-symbolS *symbolP;
-       name = input_line_pointer;
-
-
-
-       c = get_symbol_end();
-       p = input_line_pointer;
-       *p = c;
-       SKIP_WHITESPACE();
-       if (*input_line_pointer != ',') {
-               as_bad("Expected comma after name");
-               ignore_rest_of_line();
-               return;
+    char *name;
+    char c;
+    int temp;
+    char *p;
+    symbolS *symbolP;
+    name = input_line_pointer;
+
+    c = get_symbol_end();
+    p = input_line_pointer;
+    *p = c;
+    SKIP_WHITESPACE();
+    if (*input_line_pointer != ',') {
+           as_bad("Expected comma after name");
+           ignore_rest_of_line();
+           return;
        }
-       if (*input_line_pointer == '\n') {
-               as_bad("Missing size expression");
-               return;
+    if (*input_line_pointer == '\n') {
+           as_bad("Missing size expression");
+           return;
        }
-input_line_pointer++;
-       if ((temp = get_absolute_expression ()) < 0) {
-               as_warn("lcomm length (%d.) <0! Ignored.", temp);
-               ignore_rest_of_line();
-               return;
+    input_line_pointer++;
+    if ((temp = get_absolute_expression ()) < 0) {
+           as_warn("lcomm length (%d.) <0! Ignored.", temp);
+           ignore_rest_of_line();
+           return;
        }
-       *p = 0;
-       symbolP = symbol_find_or_make(name);
-       S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
-       S_SET_SEGMENT(symbolP, SEG_E2);
-       segment_info[SEG_E2].scnhdr.s_size += temp;
-       S_SET_STORAGE_CLASS(symbolP, C_STAT);
-       demand_empty_rest_of_line();
+    *p = 0;
+    symbolP = symbol_find_or_make(name);
+    S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
+    S_SET_SEGMENT(symbolP, SEG_E2);
+    segment_info[SEG_E2].scnhdr.s_size += temp;
+    S_SET_STORAGE_CLASS(symbolP, C_STAT);
+    demand_empty_rest_of_line();
 }