home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / binutils.7 / binutils / binutils-2.7 / gas / config / obj-ieee.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-04  |  12.3 KB  |  617 lines

  1. /* obj-format for ieee-695 records.
  2.    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GAS, the GNU Assembler.
  5.  
  6.    GAS is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    GAS is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with GAS; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  19.  
  20.  
  21. /*
  22.   created by
  23.  
  24.   steve chamberlain steve@cygnus.com
  25.   */
  26.  
  27. /*
  28.   this will hopefully become the port through which bfd and gas talk,
  29.   for the moment, only ieee is known to work well.
  30.   */
  31.  
  32. #include "bfd.h"
  33. #include "as.h"
  34. #include "subsegs.h"
  35. #include "output-file.h"
  36. #include "frags.h"
  37.  
  38. bfd *abfd;
  39.  
  40. /* How many addresses does the .align take? */
  41. static relax_addressT
  42. relax_align (address, alignment)
  43.      register relax_addressT address;    /* Address now. */
  44.      register long alignment;    /* Alignment (binary). */
  45. {
  46.   relax_addressT mask;
  47.   relax_addressT new_address;
  48.  
  49.   mask = ~((~0) << alignment);
  50.   new_address = (address + mask) & (~mask);
  51.   return (new_address - address);
  52. }                /* relax_align() */
  53.  
  54. /* calculate the size of the frag chain and create a bfd section
  55.    to contain all of it */
  56. static void
  57. DEFUN (size_section, (abfd, idx),
  58.        bfd * abfd AND
  59.        unsigned int idx)
  60. {
  61.   asection *sec;
  62.   unsigned int size = 0;
  63.   fragS *frag = segment_info[idx].frag_root;
  64.   while (frag)
  65.     {
  66.       if (frag->fr_address != size)
  67.     {
  68.       printf ("Out of step\n");
  69.       size = frag->fr_address;
  70.     }
  71.       size += frag->fr_fix;
  72.       switch (frag->fr_type)
  73.     {
  74.     case rs_fill:
  75.     case rs_org:
  76.       size += frag->fr_offset * frag->fr_var;
  77.       break;
  78.     case rs_align:
  79.       size += relax_align (size, frag->fr_offset);
  80.     }
  81.       frag = frag->fr_next;
  82.     }
  83.   if (size)
  84.     {
  85.       char *name = segment_info[idx].name;
  86.       if (name == (char *) NULL)
  87.     {
  88.       name = ".data";
  89.     }
  90.       segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name));
  91.       /* Make it output through itself */
  92.       sec->output_section = sec;
  93.       sec->flags |= SEC_HAS_CONTENTS;
  94.       bfd_set_section_size (abfd, sec, size);
  95.     }
  96. }
  97.  
  98. /* run through a frag chain and write out the data to go with it */
  99. static void
  100. DEFUN (fill_section, (abfd, idx),
  101.        bfd * abfd AND
  102.        unsigned int idx)
  103. {
  104.   asection *sec = segment_info[idx].user_stuff;
  105.   if (sec)
  106.     {
  107.       fragS *frag = segment_info[idx].frag_root;
  108.       unsigned int offset = 0;
  109.       while (frag)
  110.     {
  111.       unsigned int fill_size;
  112.       unsigned int count;
  113.       switch (frag->fr_type)
  114.         {
  115.         case rs_fill:
  116.         case rs_align:
  117.         case rs_org:
  118.           if (frag->fr_fix)
  119.         {
  120.           bfd_set_section_contents (abfd,
  121.                         sec,
  122.                         frag->fr_literal,
  123.                         frag->fr_address,
  124.                         frag->fr_fix);
  125.         }
  126.           offset += frag->fr_fix;
  127.           fill_size = frag->fr_var;
  128.           if (fill_size)
  129.         {
  130.           unsigned int off = frag->fr_fix;
  131.           for (count = frag->fr_offset; count; count--)
  132.             {
  133.               bfd_set_section_contents (abfd, sec,
  134.                         frag->fr_literal +
  135.                         frag->fr_fix,
  136.                         frag->fr_address + off,
  137.                         fill_size);
  138.               off += fill_size;
  139.             }
  140.         }
  141.           break;
  142.         default:
  143.           abort ();
  144.         }
  145.       frag = frag->fr_next;
  146.     }
  147.     }
  148. }
  149.  
  150. /* Count the relocations in a chain */
  151.  
  152. static unsigned int
  153. DEFUN (count_entries_in_chain, (idx),
  154.        unsigned int idx)
  155. {
  156.   unsigned int nrelocs;
  157.   fixS *fixup_ptr;
  158.  
  159.   /* Count the relocations */
  160.   fixup_ptr = segment_info[idx].fix_root;
  161.   nrelocs = 0;
  162.   while (fixup_ptr != (fixS *) NULL)
  163.     {
  164.       fixup_ptr = fixup_ptr->fx_next;
  165.       nrelocs++;
  166.     }
  167.   return nrelocs;
  168. }
  169.  
  170. /* output all the relocations for a section */
  171. void
  172. DEFUN (do_relocs_for, (idx),
  173.        unsigned int idx)
  174. {
  175.   unsigned int nrelocs;
  176.   arelent **reloc_ptr_vector;
  177.   arelent *reloc_vector;
  178.   asymbol **ptrs;
  179.   asection *section = (asection *) (segment_info[idx].user_stuff);
  180.   unsigned int i;
  181.   fixS *from;
  182.   if (section)
  183.     {
  184.       nrelocs = count_entries_in_chain (idx);
  185.  
  186.       reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *));
  187.       reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent));
  188.       ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *));
  189.       from = segment_info[idx].fix_root;
  190.       for (i = 0; i < nrelocs; i++)
  191.     {
  192.       arelent *to = reloc_vector + i;
  193.       asymbol *s;
  194.       reloc_ptr_vector[i] = to;
  195.       to->howto = (reloc_howto_type *) (from->fx_r_type);
  196.  
  197. #if 0      /* We can't represent complicated things in a reloc yet */
  198.       if (from->fx_addsy == 0 || from->fx_subsy != 0) abort();
  199. #endif
  200.  
  201.       s = &(from->fx_addsy->sy_symbol.sy);
  202.       to->address = ((char *) (from->fx_frag->fr_address +
  203.                    from->fx_where))
  204.         - ((char *) (&(from->fx_frag->fr_literal)));
  205.       to->addend = from->fx_offset;
  206.       /* If we know the symbol which we want to relocate to, turn
  207.          this reloaction into a section relative.
  208.  
  209.          If this relocation is pcrelative, and we know the
  210.          destination, we still want to keep the relocation - since
  211.          the linker might relax some of the bytes, but it stops
  212.          being pc relative and turns into an absolute relocation. */
  213.       if (s)
  214.         {
  215.           if ((s->flags & BSF_UNDEFINED) == 0)
  216.         {
  217.           to->section = s->section;
  218.  
  219.           /* We can refer directly to the value field here,
  220.              rather than using S_GET_VALUE, because this is
  221.              only called after do_symbols, which sets up the
  222.              value field.  */
  223.           to->addend += s->value;
  224.  
  225.           to->sym_ptr_ptr = 0;
  226.           if (to->howto->pcrel_offset)
  227.             {
  228.               /* This is a pcrel relocation, the addend should be adjusted */
  229.               to->addend -= to->address + 1;
  230.             }
  231.         }
  232.           else
  233.         {
  234.           to->section = 0;
  235.           *ptrs = &(from->fx_addsy->sy_symbol.sy);
  236.           to->sym_ptr_ptr = ptrs;
  237.  
  238.           if (to->howto->pcrel_offset)
  239.             {
  240.               /* This is a pcrel relocation, the addend should be adjusted */
  241.               to->addend -= to->address - 1;
  242.             }
  243.         }
  244.  
  245.         }
  246.       else
  247.         {
  248.           to->section = 0;
  249.         }
  250.  
  251.       ptrs++;
  252.       from = from->fx_next;
  253.     }
  254.  
  255.       /* attatch to the section */
  256.       section->orelocation = reloc_ptr_vector;
  257.       section->reloc_count = nrelocs;
  258.       section->flags |= SEC_LOAD;
  259.     }
  260. }
  261.  
  262. /* do the symbols.. */
  263. static void
  264. DEFUN (do_symbols, (abfd),
  265.        bfd * abfd)
  266. {
  267.   extern symbolS *symbol_rootP;
  268.   symbolS *ptr;
  269.   asymbol **symbol_ptr_vec;
  270.   asymbol *symbol_vec;
  271.   unsigned int count = 0;
  272.   unsigned int index;
  273.  
  274.  
  275.   for (ptr = symbol_rootP;
  276.        ptr != (symbolS *) NULL;
  277.        ptr = ptr->sy_next)
  278.     {
  279.       if (SEG_NORMAL (ptr->sy_symbol.seg))
  280.     {
  281.       ptr->sy_symbol.sy.section =
  282.         (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff);
  283.       S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address);
  284.       if (ptr->sy_symbol.sy.flags == 0)
  285.         {
  286.           ptr->sy_symbol.sy.flags = BSF_LOCAL;
  287.         }
  288.     }
  289.       else
  290.     {
  291.       switch (ptr->sy_symbol.seg)
  292.         {
  293.         case SEG_ABSOLUTE:
  294.           ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
  295.           ptr->sy_symbol.sy.section = 0;
  296.           break;
  297.         case SEG_UNKNOWN:
  298.           ptr->sy_symbol.sy.flags = BSF_UNDEFINED;
  299.           ptr->sy_symbol.sy.section = 0;
  300.           break;
  301.         default:
  302.           abort ();
  303.         }
  304.     }
  305.       ptr->sy_symbol.sy.value = S_GET_VALUE (ptr);
  306.       count++;
  307.     }
  308.   symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *));
  309.  
  310.   index = 0;
  311.   for (ptr = symbol_rootP;
  312.        ptr != (symbolS *) NULL;
  313.        ptr = ptr->sy_next)
  314.     {
  315.       symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
  316.       index++;
  317.     }
  318.   symbol_ptr_vec[index] = 0;
  319.   abfd->outsymbols = symbol_ptr_vec;
  320.   abfd->symcount = count;
  321. }
  322.  
  323. /* The generic as->bfd converter. Other backends may have special case
  324.    code */
  325.  
  326. void
  327. DEFUN_VOID (bfd_as_write_hook)
  328. {
  329.   int i;
  330.  
  331.   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  332.     {
  333.       size_section (abfd, i);
  334.     }
  335.  
  336.  
  337.   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  338.     fill_section (abfd, i);
  339.  
  340.   do_symbols (abfd);
  341.  
  342.   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  343.     do_relocs_for (i);
  344.  
  345. }
  346.  
  347. S_SET_SEGMENT (x, y)
  348.      symbolS *x;
  349.      int y;
  350. {
  351.   x->sy_symbol.seg = y;
  352. }
  353.  
  354. S_IS_DEFINED (x)
  355.      symbolS *x;
  356. {
  357.   if (SEG_NORMAL (x->sy_symbol.seg))
  358.     {
  359.       return 1;
  360.     }
  361.   switch (x->sy_symbol.seg)
  362.     {
  363.     case SEG_UNKNOWN:
  364.       return 0;
  365.     default:
  366.       abort ();
  367.     }
  368. }
  369.  
  370. S_IS_EXTERNAL (x)
  371. {
  372.   abort ();
  373. }
  374.  
  375. S_GET_DESC (x)
  376. {
  377.   abort ();
  378. }
  379.  
  380. S_GET_SEGMENT (x)
  381.      symbolS *x;
  382. {
  383.   return x->sy_symbol.seg;
  384. }
  385.  
  386. S_SET_EXTERNAL (x)
  387.      symbolS *x;
  388. {
  389.   x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
  390. }
  391.  
  392. S_SET_NAME (x, y)
  393.      symbolS *x;
  394.      char *y;
  395. {
  396.   x->sy_symbol.sy.name = y;
  397. }
  398.  
  399. S_GET_OTHER (x)
  400. {
  401.   abort ();
  402. }
  403.  
  404. S_IS_DEBUG (x)
  405. {
  406.   abort ();
  407. }
  408.  
  409. char *
  410. segment_name ()
  411. {
  412.   abort ();
  413. }
  414.  
  415. void
  416. obj_read_begin_hook ()
  417. {
  418. }
  419.  
  420. static void
  421. obj_ieee_section (ignore)
  422.      int ignore;
  423. {
  424.   extern char *input_line_pointer;
  425.   extern char is_end_of_line[];
  426.   char *p = input_line_pointer;
  427.   char *s = p;
  428.   int i;
  429.   /* Look up the name, if it doesn't exist, make it */
  430.   while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p])
  431.     {
  432.       p++;
  433.     }
  434.   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  435.     {
  436.       if (segment_info[i].hadone)
  437.     {
  438.       if (strncmp (segment_info[i].name, s, p - s) == 0)
  439.         {
  440.           goto ok;
  441.  
  442.         }
  443.     }
  444.       else
  445.     break;
  446.     }
  447.   if (i == SEG_UNKNOWN)
  448.     {
  449.       as_bad ("too many sections");
  450.       return;
  451.     }
  452.  
  453.   segment_info[i].hadone = 1;
  454.   segment_info[i].name = malloc (p - s + 1);
  455.   memcpy (segment_info[i].name, s, p - s);
  456.   segment_info[i].name[p - s] = 0;
  457. ok:
  458.   subseg_set (i, 0);
  459.   while (!is_end_of_line[*p])
  460.     p++;
  461.   input_line_pointer = p;
  462.  
  463. }
  464.  
  465.  
  466. void cons ();
  467. void s_ignore ();
  468.  
  469.  
  470. void s_globl ();
  471. const pseudo_typeS obj_pseudo_table[] =
  472. {
  473.   {"section", obj_ieee_section, 0},
  474.   {"data.b", cons, 1},
  475.   {"data.w", cons, 2},
  476.   {"data.l", cons, 4},
  477.   {"export", s_globl, 0},
  478.   {"option", s_ignore, 0},
  479.   {"end", s_ignore, 0},
  480.   {"import", s_ignore, 0},
  481.   {"sdata", stringer, 0},
  482.   0,
  483.  
  484. };
  485.  
  486.  
  487.  
  488. void
  489. obj_symbol_new_hook (symbolP)
  490.      symbolS *symbolP;
  491. {
  492.   symbolP->sy_symbol.sy.the_bfd = abfd;
  493. }
  494.  
  495.  
  496.  
  497.  
  498.  
  499. #if 1
  500. extern void
  501. DEFUN_VOID (write_object_file)
  502. {
  503.   int i;
  504.   struct frchain *frchain_ptr;
  505.   struct frag *frag_ptr;
  506.  
  507.   abfd = bfd_openw (out_file_name, "ieee");
  508.  
  509.   if (abfd == 0)
  510.     {
  511.       as_perror ("FATAL: Can't create %s", out_file_name);
  512.       exit (EXIT_FAILURE);
  513.     }
  514.   bfd_set_format (abfd, bfd_object);
  515.   bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
  516.   subseg_set (1, 0);
  517.   subseg_set (2, 0);
  518.   subseg_set (3, 0);
  519.   for (frchain_ptr = frchain_root;
  520.        frchain_ptr != (struct frchain *) NULL;
  521.        frchain_ptr = frchain_ptr->frch_next)
  522.     {
  523.       /* Run through all the sub-segments and align them up. Also close any
  524.      open frags. We tack a .fill onto the end of the frag chain so
  525.      that any .align's size can be worked by looking at the next
  526.      frag.  */
  527.  
  528.       subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
  529. #ifndef SUB_SEGMENT_ALIGN
  530. #define SUB_SEGMENT_ALIGN(SEG) 2
  531. #endif
  532.       frag_align (SUB_SEGMENT_ALIGN (now_seg), 0);
  533.       frag_wane (frag_now);
  534.       frag_now->fr_fix = 0;
  535.       know (frag_now->fr_next == NULL);
  536.     }
  537.  
  538.   /* Now build one big frag chain for each segment, linked through
  539.        fr_next. */
  540.   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  541.     {
  542.  
  543.       fragS **prev_frag_ptr_ptr;
  544.       struct frchain *next_frchain_ptr;
  545.  
  546.       /*    struct frag **head_ptr = segment_info[i].frag_root;*/
  547.  
  548.       segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
  549. #if 0
  550.       /* Im not sure what this is for */
  551.       for (frchain_ptr = segment_info[i].frchainP->frch_root;
  552.        frchain_ptr != (struct frchain *) NULL;
  553.        frchain_ptr = frchain_ptr->frch_next)
  554.     {
  555.       *head_ptr = frchain_ptr;
  556.       head_ptr = &frchain_ptr->next;
  557.     }
  558.  
  559.  
  560. #endif
  561.     }
  562.  
  563.   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  564.     {
  565.       relax_segment (segment_info[i].frag_root, i);
  566.     }
  567.  
  568.   /* Now the addresses of the frags are correct within the segment */
  569.  
  570.   bfd_as_write_hook ();
  571.   bfd_close (abfd);
  572. }
  573.  
  574. #endif
  575.  
  576. H_SET_TEXT_SIZE (a, b)
  577. {
  578.   abort ();
  579. }
  580.  
  581. H_GET_TEXT_SIZE ()
  582. {
  583.   abort ();
  584. }
  585.  
  586. H_SET_BSS_SIZE ()
  587. {
  588.   abort ();
  589. }
  590.  
  591. H_SET_STRING_SIZE ()
  592. {
  593.   abort ();
  594. }
  595.  
  596. H_SET_RELOCATION_SIZE ()
  597. {
  598.   abort ();
  599. }
  600.  
  601. H_SET_MAGIC_NUMBER ()
  602. {
  603.   abort ();
  604. }
  605.  
  606. H_GET_FILE_SIZE ()
  607. {
  608.   abort ();
  609. }
  610.  
  611. H_GET_TEXT_RELOCATION_SIZE ()
  612. {
  613.   abort ();
  614. }
  615.  
  616. /* end of obj-ieee.c */
  617.