home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / gdb-4.12.tar.gz / gdb-4.12.tar / gdb-4.12 / bfd / coff-rs6000.c < prev    next >
C/C++ Source or Header  |  1994-02-03  |  10KB  |  373 lines

  1. /* BFD back-end for IBM RS/6000 "XCOFF" files.
  2.    Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  3.    FIXME: Can someone provide a transliteration of this name into ASCII?
  4.    Using the following chars caused a compiler warning on HIUX (so I replaced
  5.    them with octal escapes), and isn't useful without an understanding of what
  6.    character set it is.
  7.    Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365, 
  8.      and John Gilmore.
  9.    Archive support from Damon A. Permezel.
  10.    Contributed by IBM Corporation and Cygnus Support.
  11.  
  12. This file is part of BFD, the Binary File Descriptor library.
  13.  
  14. This program is free software; you can redistribute it and/or modify
  15. it under the terms of the GNU General Public License as published by
  16. the Free Software Foundation; either version 2 of the License, or
  17. (at your option) any later version.
  18.  
  19. This program is distributed in the hope that it will be useful,
  20. but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. GNU General Public License for more details.
  23.  
  24. You should have received a copy of the GNU General Public License
  25. along with this program; if not, write to the Free Software
  26. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  27.  
  28. /* This port currently only handles reading object files, except when
  29.    compiled on an RS/6000 host.  -- no archive support, no core files.
  30.    In all cases, it does not support writing.
  31.  
  32.    FIXMEmgo comments are left from Metin Ozisik's original port.  */
  33.  
  34. /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
  35. #define RS6000COFF_C 1
  36.  
  37. #include "bfd.h"
  38. #include "sysdep.h"
  39. #include "libbfd.h"
  40. #include "obstack.h"
  41. #include "coff/internal.h"
  42. #include "coff/rs6000.h"
  43. #include "libcoff.h"
  44.  
  45. /* The main body of code is in coffcode.h.  */
  46.  
  47. /* Can't read rs6000 relocs */
  48. static reloc_howto_type dummy_reloc =
  49.   HOWTO (0,            /* type */
  50.      0,            /* rightshift */
  51.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  52.      8,            /* bitsize */
  53.      false,            /* pc_relative */
  54.      0,            /* bitpos */
  55.      complain_overflow_dont, /* complain_on_overflow */
  56.      0,            /* special_function */
  57.      "UNKNOWN",        /* name */
  58.      false,            /* partial_inplace */
  59.      0,            /* src_mask */
  60.      0,            /* dst_mask */
  61.      false);        /* pcrel_offset */
  62.  
  63. #define RTYPE2HOWTO(cache_ptr, dst) cache_ptr->howto = &dummy_reloc;
  64.  
  65. #include "coffcode.h"
  66.  
  67. #define    coff_archive_p        bfd_generic_archive_p
  68. #define    coff_mkarchive        _bfd_generic_mkarchive
  69.  
  70. #ifdef ARCHIVES_PLEASE
  71.  
  72. /* ------------------------------------------------------------------------ */
  73. /*    Support for archive file stuff..                    */
  74. /*    Stolen from Damon A. Permezel's `bfd' portation.            */
  75. /* ------------------------------------------------------------------------ */
  76.  
  77. #undef    coff_openr_next_archived_file
  78. #define coff_openr_next_archived_file    rs6000coff_openr_next_archived_file
  79.  
  80. #undef    coff_write_armap
  81. #define coff_write_armap        rs6000coff_write_armap
  82.  
  83. #undef    coff_stat_arch_elt
  84. #define    coff_stat_arch_elt        rs6000coff_stat_arch_elt
  85.  
  86. #undef    coff_snarf_ar_hdr
  87. #define    coff_snarf_ar_hdr        rs6000coff_snarf_ar_hdr
  88.  
  89. #undef    coff_mkarchive
  90. #define    coff_mkarchive            rs6000coff_mkarchive
  91.  
  92. #undef    coff_archive_p
  93. #define    coff_archive_p            rs6000coff_archive_p
  94.  
  95. #include "/usr/include/ar.h"        /* <ar.h> doesn't do it.    */
  96.  
  97.  
  98. #define arch_hdr(bfd)         \
  99.     ((struct ar_hdr *)    \
  100.      (((struct areltdata *)((bfd)->arelt_data))->arch_header))
  101.  
  102.  
  103. static boolean
  104. rs6000coff_mkarchive (abfd)
  105.      bfd *abfd;
  106. {
  107.     bfd_error = invalid_operation;    /* write not supported    */
  108. }
  109.  
  110.  
  111. /* This functions reads an arch header and returns an areltdata pointer, or
  112.    NULL on error.
  113.  
  114.    Presumes the file pointer is already in the right place (ie pointing
  115.    to the ar_hdr in the file).   Moves the file pointer; on success it
  116.    should be pointing to the front of the file contents; on failure it
  117.    could have been moved arbitrarily.
  118. */
  119.  
  120. struct areltdata *
  121. rs6000coff_snarf_ar_hdr (abfd)
  122.      bfd *abfd;
  123. {
  124.     extern int errno;
  125.  
  126.     struct {
  127.         struct ar_hdr hdr;
  128.         char namebuf[256];
  129.     } h;
  130.     int size;
  131.     struct areltdata *ared;
  132.     unsigned int namelen = 0;
  133.     char *allocptr;
  134.  
  135.     size = sizeof (h.hdr);
  136.     if (bfd_read(&h.hdr, 1, size, abfd) != size) {
  137.         bfd_error = no_more_archived_files;
  138.         return NULL;
  139.     }
  140.     size  = atoi(h.hdr.ar_namlen);    /* ar_name[] length    */
  141.     size += size & 1;
  142.  
  143.     if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
  144.         bfd_error = no_more_archived_files;
  145.         return NULL;
  146.     }
  147.  
  148.     if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
  149.         bfd_error = malformed_archive;
  150.         return NULL;
  151.     }
  152.  
  153.     h.hdr._ar_name.ar_name[size] = 0;    /* terminate filename    */
  154.  
  155.     /*
  156.      * if the filename is NULL, we're (probably) at the end.
  157.      */
  158.     if (size == 0) {
  159.         bfd_error = no_more_archived_files;
  160.         return NULL;
  161.     }
  162.  
  163.     size += sizeof (h.hdr);
  164.     allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
  165.  
  166.     if (allocptr == NULL) {
  167.         bfd_error = no_memory;
  168.         return NULL;
  169.     }
  170.  
  171.     ared = (struct areltdata *) allocptr;
  172.  
  173.     ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
  174.     memcpy ((char *) ared->arch_header, &h.hdr, size);
  175.     ared->parsed_size = atoi(h.hdr.ar_size);
  176.     ared->filename    = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
  177.  
  178.     return ared;
  179. }
  180.  
  181. /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
  182.    Why wasn't this part of the transfer vector?  */
  183.  
  184. bfd *
  185. rs6000coff_get_elt_at_filepos (archive, filepos)
  186.      bfd *archive;
  187.      file_ptr filepos;
  188. {
  189.   struct areltdata *new_areldata;
  190.   bfd *n_nfd;
  191.  
  192.   n_nfd = look_for_bfd_in_cache (archive, filepos);
  193.   if (n_nfd) return n_nfd;
  194.  
  195.   if (0 != bfd_seek (archive, filepos, SEEK_SET)) {
  196.     bfd_error = system_call_error;
  197.     return NULL;
  198.   }
  199.  
  200.   if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
  201.   
  202.   n_nfd = _bfd_create_empty_archive_element_shell (archive);
  203.   if (n_nfd == NULL) {
  204.     bfd_release (archive, (PTR)new_areldata);
  205.     return NULL;
  206.   }
  207.   n_nfd->origin = bfd_tell (archive);
  208.   n_nfd->arelt_data = (PTR) new_areldata;
  209.   n_nfd->filename = new_areldata->filename;
  210.  
  211.   if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
  212.     return n_nfd;
  213.  
  214.   /* huh? */
  215.   bfd_release (archive, (PTR)n_nfd);
  216.   bfd_release (archive, (PTR)new_areldata);
  217.   return NULL;
  218. }
  219.  
  220. /*
  221.  * xcoff_openr_next_archived_file -    xcoff has nxt/prv seek addrs.
  222.  */
  223. static bfd *
  224. rs6000coff_openr_next_archived_file(archive, last_file)
  225.   bfd *archive, *last_file; 
  226. {
  227.     file_ptr filestart;
  228.  
  229.     if (!last_file)
  230.         filestart = bfd_ardata(archive)->first_file_filepos;
  231.     else
  232.         filestart = atol(arch_hdr(last_file)->ar_nxtmem);
  233.  
  234.     return rs6000coff_get_elt_at_filepos (archive, filestart);
  235. }
  236.  
  237.  
  238. static bfd_target *
  239. rs6000coff_archive_p (abfd)
  240.      bfd *abfd;
  241. {
  242.     struct fl_hdr hdr;
  243.     register struct artdata *art;
  244.  
  245.     if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
  246.         bfd_error = wrong_format;
  247.         return 0;
  248.     }
  249.  
  250.     if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
  251.         bfd_error = wrong_format;
  252.         return 0;
  253.     }
  254.  
  255.     /*
  256.      * bfd_ardata() accesses the bfd->tdata field.
  257.      */
  258.     abfd->tdata.aout_ar_data =
  259.       (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
  260.     if ((art = bfd_ardata (abfd)) == NULL) {
  261.         bfd_error = no_memory;
  262.         return 0;
  263.     }
  264.  
  265.     art->first_file_filepos = atoi(hdr.fl_fstmoff);
  266.     *(struct fl_hdr *) (1 + art) = hdr;
  267.  
  268.     /* Someday...
  269.      * slurp in the member table, which I think is the armap equivalent.
  270.     xcoff_slurp_armap(abfd);
  271.      */
  272.   
  273.     return abfd->xvec;
  274. }
  275.  
  276.  
  277. static int
  278. rs6000coff_stat_arch_elt(abfd, buf)
  279.   bfd *abfd;
  280.   struct stat *buf;
  281. {
  282.     struct ar_hdr *hdr;
  283.     char *aloser;
  284.   
  285.     if (abfd->arelt_data == NULL) {
  286.         bfd_error = invalid_operation;
  287.         return -1;
  288.     }
  289.     
  290.     hdr = arch_hdr (abfd);
  291.  
  292. #define foo(arelt, stelt, size)  \
  293.     buf->stelt = strtol (hdr->arelt, &aloser, size); \
  294.         if (aloser == hdr->arelt) return -1;
  295.   
  296.     foo (ar_date, st_mtime, 10);
  297.     foo (ar_uid, st_uid, 10);
  298.     foo (ar_gid, st_gid, 10);
  299.     foo (ar_mode, st_mode, 8);
  300.     foo (ar_size, st_size, 10);
  301. #undef foo
  302.  
  303.     return 0;
  304. }
  305.  
  306. static boolean
  307. rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
  308.   bfd *arch;
  309.   unsigned int elength;
  310.   struct orl *map; 
  311. {
  312.     bfd_error = invalid_operation;
  313.     return false;
  314. }
  315. #endif    /* ARCHIVES_PLEASE */
  316.  
  317.  
  318. #ifdef COREFILES_PLEASE
  319. extern bfd_target * rs6000coff_core_p ();
  320. extern boolean rs6000coff_get_section_contents ();
  321. extern boolean rs6000coff_core_file_matches_executable_p ();
  322.  
  323. #undef    coff_core_file_matches_executable_p
  324. #define coff_core_file_matches_executable_p  \
  325.                      rs6000coff_core_file_matches_executable_p
  326.  
  327. #undef    coff_get_section_contents
  328. #define    coff_get_section_contents    rs6000coff_get_section_contents
  329. #endif
  330.  
  331. /* The transfer vector that leads the outside world to all of the above. */
  332.  
  333. bfd_target rs6000coff_vec =
  334. {
  335.   "aixcoff-rs6000",        /* name */
  336.   bfd_target_coff_flavour,    
  337.   true,                /* data byte order is big */
  338.   true,                /* header byte order is big */
  339.  
  340.   (HAS_RELOC | EXEC_P |        /* object flags */
  341.    HAS_LINENO | HAS_DEBUG |
  342.    HAS_SYMS | HAS_LOCALS | WP_TEXT),
  343.  
  344.   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
  345.   0,                /* leading char */
  346.   '/',                /* ar_pad_char */
  347.   15,                /* ar_max_namelen??? FIXMEmgo */
  348.   3,                /* default alignment power */
  349.  
  350.   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
  351.      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
  352.      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
  353.   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
  354.      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
  355.      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
  356.  
  357.   {_bfd_dummy_target, coff_object_p,     /* bfd_check_format */
  358.      coff_archive_p,
  359. #ifdef    COREFILES_PLEASE
  360.      rs6000coff_core_p
  361. #else
  362.      _bfd_dummy_target
  363. #endif
  364.        },
  365.   {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
  366.      bfd_false},
  367.   {bfd_false, coff_write_object_contents,    /* bfd_write_contents */
  368.      _bfd_write_archive_contents, bfd_false},
  369.  
  370.   JUMP_TABLE(coff),
  371.   COFF_SWAP_TABLE,
  372. };
  373.