Home | History | Annotate | Line # | Download | only in libiberty
simple-object-xcoff.c revision 1.1
      1  1.1  christos /* simple-object-coff.c -- routines to manipulate XCOFF object files.
      2  1.1  christos    Copyright 2013 Free Software Foundation, Inc.
      3  1.1  christos    Written by Ian Lance Taylor, Google and David Edelsohn, IBM.
      4  1.1  christos 
      5  1.1  christos This program is free software; you can redistribute it and/or modify it
      6  1.1  christos under the terms of the GNU General Public License as published by the
      7  1.1  christos Free Software Foundation; either version 2, or (at your option) any
      8  1.1  christos later version.
      9  1.1  christos 
     10  1.1  christos This program is distributed in the hope that it will be useful,
     11  1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos You should have received a copy of the GNU General Public License
     16  1.1  christos along with this program; if not, write to the Free Software
     17  1.1  christos Foundation, 51 Franklin Street - Fifth Floor,
     18  1.1  christos Boston, MA 02110-1301, USA.  */
     19  1.1  christos 
     20  1.1  christos #include "config.h"
     21  1.1  christos #include "libiberty.h"
     22  1.1  christos #include "simple-object.h"
     23  1.1  christos 
     24  1.1  christos #include <errno.h>
     25  1.1  christos #include <stddef.h>
     26  1.1  christos 
     27  1.1  christos #ifdef HAVE_STDLIB_H
     28  1.1  christos #include <stdlib.h>
     29  1.1  christos #endif
     30  1.1  christos 
     31  1.1  christos #ifdef HAVE_STDINT_H
     32  1.1  christos #include <stdint.h>
     33  1.1  christos #endif
     34  1.1  christos 
     35  1.1  christos #ifdef HAVE_STRING_H
     36  1.1  christos #include <string.h>
     37  1.1  christos #endif
     38  1.1  christos 
     39  1.1  christos #ifdef HAVE_INTTYPES_H
     40  1.1  christos #include <inttypes.h>
     41  1.1  christos #endif
     42  1.1  christos 
     43  1.1  christos #include "simple-object-common.h"
     44  1.1  christos 
     45  1.1  christos /* XCOFF structures and constants.  */
     46  1.1  christos 
     47  1.1  christos /* XCOFF file header.  */
     48  1.1  christos 
     49  1.1  christos struct external_filehdr
     50  1.1  christos {
     51  1.1  christos   unsigned char f_magic[2];	/* magic number			*/
     52  1.1  christos   unsigned char f_nscns[2];	/* number of sections		*/
     53  1.1  christos   unsigned char f_timdat[4];	/* time & date stamp		*/
     54  1.1  christos   union
     55  1.1  christos   {
     56  1.1  christos     struct
     57  1.1  christos     {
     58  1.1  christos       unsigned char f_symptr[4];	/* file pointer to symtab	*/
     59  1.1  christos       unsigned char f_nsyms[4];	/* number of symtab entries	*/
     60  1.1  christos       unsigned char f_opthdr[2];	/* sizeof(optional hdr)		*/
     61  1.1  christos       unsigned char f_flags[2];	/* flags			*/
     62  1.1  christos     } xcoff32;
     63  1.1  christos     struct
     64  1.1  christos     {
     65  1.1  christos       unsigned char f_symptr[8];	/* file pointer to symtab	*/
     66  1.1  christos       unsigned char f_opthdr[2];	/* sizeof(optional hdr)		*/
     67  1.1  christos       unsigned char f_flags[2];	/* flags			*/
     68  1.1  christos       unsigned char f_nsyms[4];	/* number of symtab entries	*/
     69  1.1  christos     } xcoff64;
     70  1.1  christos   } u;
     71  1.1  christos };
     72  1.1  christos 
     73  1.1  christos /* Bits for filehdr f_flags field.  */
     74  1.1  christos 
     75  1.1  christos #define F_EXEC			(0x0002)
     76  1.1  christos 
     77  1.1  christos /* The known values of f_magic in an XCOFF file header.  */
     78  1.1  christos 
     79  1.1  christos #define U802WRMAGIC 0730        /* Writeable text segments.  */
     80  1.1  christos #define U802ROMAGIC 0735        /* Readonly sharable text segments.  */
     81  1.1  christos #define U802TOCMAGIC 0737       /* Readonly text segments and TOC.  */
     82  1.1  christos #define U803XTOCMAGIC 0757      /* Aix 4.3 64-bit XCOFF.  */
     83  1.1  christos #define U64_TOCMAGIC 0767       /* AIX 5+ 64-bit XCOFF.  */
     84  1.1  christos 
     85  1.1  christos /* XCOFF section header.  */
     86  1.1  christos 
     87  1.1  christos struct external_scnhdr
     88  1.1  christos {
     89  1.1  christos   unsigned char s_name[8];	/* section name				*/
     90  1.1  christos   union
     91  1.1  christos   {
     92  1.1  christos     struct
     93  1.1  christos     {
     94  1.1  christos       unsigned char s_paddr[4];	/* physical address, aliased s_nlib 	*/
     95  1.1  christos       unsigned char s_vaddr[4];	/* virtual address			*/
     96  1.1  christos       unsigned char s_size[4];	/* section size				*/
     97  1.1  christos       unsigned char s_scnptr[4];	/* file ptr to raw data for section */
     98  1.1  christos       unsigned char s_relptr[4];	/* file ptr to relocation	*/
     99  1.1  christos       unsigned char s_lnnoptr[4];	/* file ptr to line numbers	*/
    100  1.1  christos       unsigned char s_nreloc[2];	/* number of relocation entries	*/
    101  1.1  christos       unsigned char s_nlnno[2];	/* number of line number entries	*/
    102  1.1  christos       unsigned char s_flags[4];	/* flags				*/
    103  1.1  christos     } xcoff32;
    104  1.1  christos     struct
    105  1.1  christos     {
    106  1.1  christos       unsigned char s_paddr[8];	/* physical address, aliased s_nlib 	*/
    107  1.1  christos       unsigned char s_vaddr[8];	/* virtual address			*/
    108  1.1  christos       unsigned char s_size[8];	/* section size				*/
    109  1.1  christos       unsigned char s_scnptr[8];	/* file ptr to raw data for section */
    110  1.1  christos       unsigned char s_relptr[8];	/* file ptr to relocation	*/
    111  1.1  christos       unsigned char s_lnnoptr[8];	/* file ptr to line numbers	*/
    112  1.1  christos       unsigned char s_nreloc[4];	/* number of relocation entries	*/
    113  1.1  christos       unsigned char s_nlnno[4];	/* number of line number entries	*/
    114  1.1  christos       unsigned char s_flags[4];	/* flags				*/
    115  1.1  christos     } xcoff64;
    116  1.1  christos   } u;
    117  1.1  christos };
    118  1.1  christos 
    119  1.1  christos #define SCNHSZ32	(40)
    120  1.1  christos #define SCNHSZ64	(68)
    121  1.1  christos 
    122  1.1  christos /* The length of the s_name field in struct external_scnhdr.  */
    123  1.1  christos 
    124  1.1  christos #define SCNNMLEN	(8)
    125  1.1  christos 
    126  1.1  christos /* Bits for scnhdr s_flags field.  */
    127  1.1  christos 
    128  1.1  christos #define STYP_DATA			0x40
    129  1.1  christos 
    130  1.1  christos /* XCOFF symbol table entry.  */
    131  1.1  christos 
    132  1.1  christos 
    133  1.1  christos #define N_SYMNMLEN	(8)	/* # characters in a symbol name	*/
    134  1.1  christos 
    135  1.1  christos /* The format of an XCOFF symbol-table entry.  */
    136  1.1  christos struct external_syment
    137  1.1  christos {
    138  1.1  christos   union {
    139  1.1  christos     struct {
    140  1.1  christos       union {
    141  1.1  christos         /* The name of the symbol.  There is an implicit null character
    142  1.1  christos            after the end of the array.  */
    143  1.1  christos         char n_name[N_SYMNMLEN];
    144  1.1  christos         struct {
    145  1.1  christos           /* If n_zeroes is zero, n_offset is the offset the name from
    146  1.1  christos              the start of the string table.  */
    147  1.1  christos           unsigned char n_zeroes[4];
    148  1.1  christos           unsigned char n_offset[4];
    149  1.1  christos         } n;
    150  1.1  christos       } n;
    151  1.1  christos 
    152  1.1  christos       /* The symbol's value.  */
    153  1.1  christos       unsigned char n_value[4];
    154  1.1  christos     } xcoff32;
    155  1.1  christos     struct {
    156  1.1  christos       /* The symbol's value.  */
    157  1.1  christos       unsigned char n_value[8];
    158  1.1  christos 
    159  1.1  christos       /* The offset of the symbol from the start of the string table.  */
    160  1.1  christos       unsigned char n_offset[4];
    161  1.1  christos     } xcoff64;
    162  1.1  christos   } u;
    163  1.1  christos 
    164  1.1  christos   /* The number of the section to which this symbol belongs.  */
    165  1.1  christos   unsigned char n_scnum[2];
    166  1.1  christos 
    167  1.1  christos   /* The type of symbol.  (It can be interpreted as an n_lang
    168  1.1  christos      and an n_cpu byte, but we don't care about that here.)  */
    169  1.1  christos   unsigned char n_type[2];
    170  1.1  christos 
    171  1.1  christos   /* The class of symbol (a C_* value).  */
    172  1.1  christos   unsigned char n_sclass[1];
    173  1.1  christos 
    174  1.1  christos   /* The number of auxiliary symbols attached to this entry.  */
    175  1.1  christos   unsigned char n_numaux[1];
    176  1.1  christos };
    177  1.1  christos 
    178  1.1  christos #define SYMESZ		(18)
    179  1.1  christos 
    180  1.1  christos /* Length allowed for filename in aux sym format 4.  */
    181  1.1  christos 
    182  1.1  christos #define FILNMLEN	(14)
    183  1.1  christos 
    184  1.1  christos /* Omits x_sym and other unused variants.  */
    185  1.1  christos 
    186  1.1  christos union external_auxent
    187  1.1  christos {
    188  1.1  christos   /* Aux sym format 4: file.  */
    189  1.1  christos   union
    190  1.1  christos   {
    191  1.1  christos     char x_fname[FILNMLEN];
    192  1.1  christos     struct
    193  1.1  christos     {
    194  1.1  christos       unsigned char x_zeroes[4];
    195  1.1  christos       unsigned char x_offset[4];
    196  1.1  christos       unsigned char x_pad[FILNMLEN-8];
    197  1.1  christos       unsigned char x_ftype;
    198  1.1  christos     } _x;
    199  1.1  christos   } x_file;
    200  1.1  christos   /* Aux sym format 5: section.  */
    201  1.1  christos   struct
    202  1.1  christos   {
    203  1.1  christos     unsigned char x_scnlen[4];		/* section length		*/
    204  1.1  christos     unsigned char x_nreloc[2];		/* # relocation entries		*/
    205  1.1  christos     unsigned char x_nlinno[2];		/* # line numbers		*/
    206  1.1  christos   } x_scn;
    207  1.1  christos   /* CSECT auxiliary entry.  */
    208  1.1  christos   union
    209  1.1  christos   {
    210  1.1  christos     struct
    211  1.1  christos     {
    212  1.1  christos       struct
    213  1.1  christos       {
    214  1.1  christos 	unsigned char x_scnlen[4];	/* csect length */
    215  1.1  christos 	unsigned char x_parmhash[4];	/* parm type hash index */
    216  1.1  christos 	unsigned char x_snhash[2];	/* sect num with parm hash */
    217  1.1  christos 	unsigned char x_smtyp;		/* symbol align and type */
    218  1.1  christos 	unsigned char x_smclas;		/* storage mapping class */
    219  1.1  christos 	unsigned char x_stab;		/* dbx stab info index */
    220  1.1  christos 	unsigned char x_snstab[2];	/* sect num with dbx stab */
    221  1.1  christos       } x_csect;
    222  1.1  christos     } xcoff32;
    223  1.1  christos     struct
    224  1.1  christos     {
    225  1.1  christos       struct
    226  1.1  christos       {
    227  1.1  christos 	unsigned char x_scnlen_lo[4];	/* csect length */
    228  1.1  christos 	unsigned char x_parmhash[4];	/* parm type hash index */
    229  1.1  christos 	unsigned char x_snhash[2];	/* sect num with parm hash */
    230  1.1  christos 	unsigned char x_smtyp;		/* symbol align and type */
    231  1.1  christos 	unsigned char x_smclas;		/* storage mapping class */
    232  1.1  christos 	unsigned char x_scnlen_hi[4];
    233  1.1  christos 	unsigned char pad;
    234  1.1  christos 	unsigned char x_auxtype;
    235  1.1  christos       } x_csect;
    236  1.1  christos     } xcoff64;
    237  1.1  christos   } u;
    238  1.1  christos   /* SECTION/DWARF auxiliary entry.  */
    239  1.1  christos   struct
    240  1.1  christos   {
    241  1.1  christos     unsigned char x_scnlen[4];		/* section length */
    242  1.1  christos     unsigned char pad1[4];
    243  1.1  christos     unsigned char x_nreloc[4];		/* number RLDs */
    244  1.1  christos   } x_sect;
    245  1.1  christos };
    246  1.1  christos 
    247  1.1  christos /* Symbol-related constants.  */
    248  1.1  christos 
    249  1.1  christos #define N_DEBUG		(-2)
    250  1.1  christos #define IMAGE_SYM_TYPE_NULL	(0)
    251  1.1  christos #define IMAGE_SYM_DTYPE_NULL	(0)
    252  1.1  christos #define IMAGE_SYM_CLASS_STATIC	(3)
    253  1.1  christos #define IMAGE_SYM_CLASS_FILE	(103)
    254  1.1  christos 
    255  1.1  christos #define IMAGE_SYM_TYPE \
    256  1.1  christos   ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
    257  1.1  christos 
    258  1.1  christos #define C_STAT		(3)
    259  1.1  christos #define C_FILE		(103)
    260  1.1  christos 
    261  1.1  christos /* Private data for an simple_object_read.  */
    262  1.1  christos 
    263  1.1  christos struct simple_object_xcoff_read
    264  1.1  christos {
    265  1.1  christos   /* Magic number.  */
    266  1.1  christos   unsigned short magic;
    267  1.1  christos   /* Number of sections.  */
    268  1.1  christos   unsigned short nscns;
    269  1.1  christos   /* File offset of symbol table.  */
    270  1.1  christos   off_t symptr;
    271  1.1  christos   /* Number of symbol table entries.  */
    272  1.1  christos   unsigned int nsyms;
    273  1.1  christos   /* Flags.  */
    274  1.1  christos   unsigned short flags;
    275  1.1  christos   /* Offset of section headers in file.  */
    276  1.1  christos   off_t scnhdr_offset;
    277  1.1  christos };
    278  1.1  christos 
    279  1.1  christos /* Private data for an simple_object_attributes.  */
    280  1.1  christos 
    281  1.1  christos struct simple_object_xcoff_attributes
    282  1.1  christos {
    283  1.1  christos   /* Magic number.  */
    284  1.1  christos   unsigned short magic;
    285  1.1  christos   /* Flags.  */
    286  1.1  christos   unsigned short flags;
    287  1.1  christos };
    288  1.1  christos 
    289  1.1  christos /* See if we have a XCOFF file.  */
    290  1.1  christos 
    291  1.1  christos static void *
    292  1.1  christos simple_object_xcoff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
    293  1.1  christos 			   int descriptor, off_t offset,
    294  1.1  christos 			   const char *segment_name ATTRIBUTE_UNUSED,
    295  1.1  christos 			   const char **errmsg, int *err)
    296  1.1  christos {
    297  1.1  christos   unsigned short magic;
    298  1.1  christos   unsigned short (*fetch_16) (const unsigned char *);
    299  1.1  christos   unsigned int (*fetch_32) (const unsigned char *);
    300  1.1  christos   ulong_type (*fetch_64) (const unsigned char *);
    301  1.1  christos   unsigned char hdrbuf[sizeof (struct external_filehdr)];
    302  1.1  christos   struct simple_object_xcoff_read *ocr;
    303  1.1  christos   int u64;
    304  1.1  christos 
    305  1.1  christos   magic = simple_object_fetch_big_16 (header);
    306  1.1  christos 
    307  1.1  christos   if (magic != U802TOCMAGIC && magic != U64_TOCMAGIC)
    308  1.1  christos     {
    309  1.1  christos       *errmsg = NULL;
    310  1.1  christos       *err = 0;
    311  1.1  christos       return NULL;
    312  1.1  christos     }
    313  1.1  christos 
    314  1.1  christos   fetch_16 = simple_object_fetch_big_16;
    315  1.1  christos   fetch_32 = simple_object_fetch_big_32;
    316  1.1  christos   fetch_64 = simple_object_fetch_big_64;
    317  1.1  christos 
    318  1.1  christos   if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
    319  1.1  christos 				    errmsg, err))
    320  1.1  christos     return NULL;
    321  1.1  christos 
    322  1.1  christos   u64 = magic == U64_TOCMAGIC;
    323  1.1  christos 
    324  1.1  christos   ocr = XNEW (struct simple_object_xcoff_read);
    325  1.1  christos   ocr->magic = magic;
    326  1.1  christos   ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
    327  1.1  christos   if (u64)
    328  1.1  christos     {
    329  1.1  christos       ocr->symptr = fetch_64 (hdrbuf
    330  1.1  christos 			      + offsetof (struct external_filehdr,
    331  1.1  christos 					  u.xcoff64.f_symptr));
    332  1.1  christos       ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr,
    333  1.1  christos 						u.xcoff64.f_nsyms));
    334  1.1  christos       ocr->scnhdr_offset = (sizeof (struct external_filehdr)
    335  1.1  christos 			    + fetch_16 (hdrbuf + offsetof (struct external_filehdr,
    336  1.1  christos 							   u.xcoff64.f_opthdr)));
    337  1.1  christos 
    338  1.1  christos     }
    339  1.1  christos   else
    340  1.1  christos     {
    341  1.1  christos       ocr->symptr = fetch_32 (hdrbuf
    342  1.1  christos 			      + offsetof (struct external_filehdr,
    343  1.1  christos 					  u.xcoff32.f_symptr));
    344  1.1  christos       ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr,
    345  1.1  christos 						u.xcoff32.f_nsyms));
    346  1.1  christos       ocr->scnhdr_offset = (sizeof (struct external_filehdr) - 4
    347  1.1  christos 			    + fetch_16 (hdrbuf + offsetof (struct external_filehdr,
    348  1.1  christos 							   u.xcoff32.f_opthdr)));
    349  1.1  christos 
    350  1.1  christos     }
    351  1.1  christos 
    352  1.1  christos   return (void *) ocr;
    353  1.1  christos }
    354  1.1  christos 
    355  1.1  christos /* Read the string table in a XCOFF file.  */
    356  1.1  christos 
    357  1.1  christos static char *
    358  1.1  christos simple_object_xcoff_read_strtab (simple_object_read *sobj, size_t *strtab_size,
    359  1.1  christos 				 const char **errmsg, int *err)
    360  1.1  christos {
    361  1.1  christos   struct simple_object_xcoff_read *ocr =
    362  1.1  christos     (struct simple_object_xcoff_read *) sobj->data;
    363  1.1  christos   off_t strtab_offset;
    364  1.1  christos   unsigned char strsizebuf[4];
    365  1.1  christos   size_t strsize;
    366  1.1  christos   char *strtab;
    367  1.1  christos 
    368  1.1  christos   strtab_offset = sobj->offset + ocr->symptr
    369  1.1  christos     + ocr->nsyms * SYMESZ;
    370  1.1  christos   if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
    371  1.1  christos 				    strsizebuf, 4, errmsg, err))
    372  1.1  christos     return NULL;
    373  1.1  christos   strsize = simple_object_fetch_big_32 (strsizebuf);
    374  1.1  christos   strtab = XNEWVEC (char, strsize);
    375  1.1  christos   if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
    376  1.1  christos 				    (unsigned char *) strtab, strsize, errmsg,
    377  1.1  christos 				    err))
    378  1.1  christos     {
    379  1.1  christos       XDELETEVEC (strtab);
    380  1.1  christos       return NULL;
    381  1.1  christos     }
    382  1.1  christos   *strtab_size = strsize;
    383  1.1  christos   return strtab;
    384  1.1  christos }
    385  1.1  christos 
    386  1.1  christos /* Find all sections in a XCOFF file.  */
    387  1.1  christos 
    388  1.1  christos static const char *
    389  1.1  christos simple_object_xcoff_find_sections (simple_object_read *sobj,
    390  1.1  christos 				  int (*pfn) (void *, const char *,
    391  1.1  christos 					      off_t offset, off_t length),
    392  1.1  christos 				  void *data,
    393  1.1  christos 				  int *err)
    394  1.1  christos {
    395  1.1  christos   struct simple_object_xcoff_read *ocr =
    396  1.1  christos     (struct simple_object_xcoff_read *) sobj->data;
    397  1.1  christos   int u64 = ocr->magic == U64_TOCMAGIC;
    398  1.1  christos   size_t scnhdr_size;
    399  1.1  christos   unsigned char *scnbuf;
    400  1.1  christos   const char *errmsg;
    401  1.1  christos   unsigned int (*fetch_32) (const unsigned char *);
    402  1.1  christos   ulong_type (*fetch_64) (const unsigned char *);
    403  1.1  christos   unsigned int nscns;
    404  1.1  christos   char *strtab;
    405  1.1  christos   size_t strtab_size;
    406  1.1  christos   unsigned int i;
    407  1.1  christos 
    408  1.1  christos   scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32;
    409  1.1  christos   scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns);
    410  1.1  christos   if (!simple_object_internal_read (sobj->descriptor,
    411  1.1  christos 				    sobj->offset + ocr->scnhdr_offset,
    412  1.1  christos 				    scnbuf, scnhdr_size * ocr->nscns, &errmsg,
    413  1.1  christos 				    err))
    414  1.1  christos     {
    415  1.1  christos       XDELETEVEC (scnbuf);
    416  1.1  christos       return errmsg;
    417  1.1  christos     }
    418  1.1  christos 
    419  1.1  christos   fetch_32 = simple_object_fetch_big_32;
    420  1.1  christos   fetch_64 = simple_object_fetch_big_64;
    421  1.1  christos 
    422  1.1  christos   nscns = ocr->nscns;
    423  1.1  christos   strtab = NULL;
    424  1.1  christos   strtab_size = 0;
    425  1.1  christos   for (i = 0; i < nscns; ++i)
    426  1.1  christos     {
    427  1.1  christos       unsigned char *scnhdr;
    428  1.1  christos       unsigned char *scnname;
    429  1.1  christos       char namebuf[SCNNMLEN + 1];
    430  1.1  christos       char *name;
    431  1.1  christos       off_t scnptr;
    432  1.1  christos       unsigned int size;
    433  1.1  christos 
    434  1.1  christos       scnhdr = scnbuf + i * scnhdr_size;
    435  1.1  christos       scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
    436  1.1  christos       memcpy (namebuf, scnname, SCNNMLEN);
    437  1.1  christos       namebuf[SCNNMLEN] = '\0';
    438  1.1  christos       name = &namebuf[0];
    439  1.1  christos       if (namebuf[0] == '/')
    440  1.1  christos 	{
    441  1.1  christos 	  size_t strindex;
    442  1.1  christos 	  char *end;
    443  1.1  christos 
    444  1.1  christos 	  strindex = strtol (namebuf + 1, &end, 10);
    445  1.1  christos 	  if (*end == '\0')
    446  1.1  christos 	    {
    447  1.1  christos 	      /* The real section name is found in the string
    448  1.1  christos 		 table.  */
    449  1.1  christos 	      if (strtab == NULL)
    450  1.1  christos 		{
    451  1.1  christos 		  strtab = simple_object_xcoff_read_strtab (sobj,
    452  1.1  christos 							   &strtab_size,
    453  1.1  christos 							   &errmsg, err);
    454  1.1  christos 		  if (strtab == NULL)
    455  1.1  christos 		    {
    456  1.1  christos 		      XDELETEVEC (scnbuf);
    457  1.1  christos 		      return errmsg;
    458  1.1  christos 		    }
    459  1.1  christos 		}
    460  1.1  christos 
    461  1.1  christos 	      if (strindex < 4 || strindex >= strtab_size)
    462  1.1  christos 		{
    463  1.1  christos 		  XDELETEVEC (strtab);
    464  1.1  christos 		  XDELETEVEC (scnbuf);
    465  1.1  christos 		  *err = 0;
    466  1.1  christos 		  return "section string index out of range";
    467  1.1  christos 		}
    468  1.1  christos 
    469  1.1  christos 	      name = strtab + strindex;
    470  1.1  christos 	    }
    471  1.1  christos 	}
    472  1.1  christos 
    473  1.1  christos       if (u64)
    474  1.1  christos 	{
    475  1.1  christos 	  scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
    476  1.1  christos 						u.xcoff64.s_scnptr));
    477  1.1  christos 	  size = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
    478  1.1  christos 					      u.xcoff64.s_size));
    479  1.1  christos 	}
    480  1.1  christos       else
    481  1.1  christos 	{
    482  1.1  christos 	  scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
    483  1.1  christos 						u.xcoff32.s_scnptr));
    484  1.1  christos 	  size = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
    485  1.1  christos 					      u.xcoff32.s_size));
    486  1.1  christos 	}
    487  1.1  christos 
    488  1.1  christos       if (!(*pfn) (data, name, scnptr, size))
    489  1.1  christos 	break;
    490  1.1  christos     }
    491  1.1  christos 
    492  1.1  christos   if (strtab != NULL)
    493  1.1  christos     XDELETEVEC (strtab);
    494  1.1  christos   XDELETEVEC (scnbuf);
    495  1.1  christos 
    496  1.1  christos   return NULL;
    497  1.1  christos }
    498  1.1  christos 
    499  1.1  christos /* Fetch the attributes for an simple_object_read.  */
    500  1.1  christos 
    501  1.1  christos static void *
    502  1.1  christos simple_object_xcoff_fetch_attributes (simple_object_read *sobj,
    503  1.1  christos 				     const char **errmsg ATTRIBUTE_UNUSED,
    504  1.1  christos 				     int *err ATTRIBUTE_UNUSED)
    505  1.1  christos {
    506  1.1  christos   struct simple_object_xcoff_read *ocr =
    507  1.1  christos     (struct simple_object_xcoff_read *) sobj->data;
    508  1.1  christos   struct simple_object_xcoff_attributes *ret;
    509  1.1  christos 
    510  1.1  christos   ret = XNEW (struct simple_object_xcoff_attributes);
    511  1.1  christos   ret->magic = ocr->magic;
    512  1.1  christos   ret->flags = ocr->flags;
    513  1.1  christos   return ret;
    514  1.1  christos }
    515  1.1  christos 
    516  1.1  christos /* Release the private data for an simple_object_read.  */
    517  1.1  christos 
    518  1.1  christos static void
    519  1.1  christos simple_object_xcoff_release_read (void *data)
    520  1.1  christos {
    521  1.1  christos   XDELETE (data);
    522  1.1  christos }
    523  1.1  christos 
    524  1.1  christos /* Compare two attributes structures.  */
    525  1.1  christos 
    526  1.1  christos static const char *
    527  1.1  christos simple_object_xcoff_attributes_merge (void *todata, void *fromdata, int *err)
    528  1.1  christos {
    529  1.1  christos   struct simple_object_xcoff_attributes *to =
    530  1.1  christos     (struct simple_object_xcoff_attributes *) todata;
    531  1.1  christos   struct simple_object_xcoff_attributes *from =
    532  1.1  christos     (struct simple_object_xcoff_attributes *) fromdata;
    533  1.1  christos 
    534  1.1  christos   if (to->magic != from->magic)
    535  1.1  christos     {
    536  1.1  christos       *err = 0;
    537  1.1  christos       return "XCOFF object format mismatch";
    538  1.1  christos     }
    539  1.1  christos   return NULL;
    540  1.1  christos }
    541  1.1  christos 
    542  1.1  christos /* Release the private data for an attributes structure.  */
    543  1.1  christos 
    544  1.1  christos static void
    545  1.1  christos simple_object_xcoff_release_attributes (void *data)
    546  1.1  christos {
    547  1.1  christos   XDELETE (data);
    548  1.1  christos }
    549  1.1  christos 
    550  1.1  christos /* Prepare to write out a file.  */
    551  1.1  christos 
    552  1.1  christos static void *
    553  1.1  christos simple_object_xcoff_start_write (void *attributes_data,
    554  1.1  christos 				const char **errmsg ATTRIBUTE_UNUSED,
    555  1.1  christos 				int *err ATTRIBUTE_UNUSED)
    556  1.1  christos {
    557  1.1  christos   struct simple_object_xcoff_attributes *attrs =
    558  1.1  christos     (struct simple_object_xcoff_attributes *) attributes_data;
    559  1.1  christos   struct simple_object_xcoff_attributes *ret;
    560  1.1  christos 
    561  1.1  christos   /* We're just going to record the attributes, but we need to make a
    562  1.1  christos      copy because the user may delete them.  */
    563  1.1  christos   ret = XNEW (struct simple_object_xcoff_attributes);
    564  1.1  christos   *ret = *attrs;
    565  1.1  christos   return ret;
    566  1.1  christos }
    567  1.1  christos 
    568  1.1  christos /* Write out a XCOFF filehdr.  */
    569  1.1  christos 
    570  1.1  christos static int
    571  1.1  christos simple_object_xcoff_write_filehdr (simple_object_write *sobj, int descriptor,
    572  1.1  christos 				  unsigned int nscns, size_t symtab_offset,
    573  1.1  christos 				  unsigned int nsyms, const char **errmsg,
    574  1.1  christos 				  int *err)
    575  1.1  christos {
    576  1.1  christos   struct simple_object_xcoff_attributes *attrs =
    577  1.1  christos     (struct simple_object_xcoff_attributes *) sobj->data;
    578  1.1  christos   int u64 = attrs->magic == U64_TOCMAGIC;
    579  1.1  christos   unsigned char hdrbuf[sizeof (struct external_filehdr)];
    580  1.1  christos   unsigned char *hdr;
    581  1.1  christos   void (*set_16) (unsigned char *, unsigned short);
    582  1.1  christos   void (*set_32) (unsigned char *, unsigned int);
    583  1.1  christos   void (*set_64) (unsigned char *, ulong_type);
    584  1.1  christos 
    585  1.1  christos   hdr = &hdrbuf[0];
    586  1.1  christos 
    587  1.1  christos   set_16 = simple_object_set_big_16;
    588  1.1  christos   set_32 = simple_object_set_big_32;
    589  1.1  christos   set_64 = simple_object_set_big_64;
    590  1.1  christos 
    591  1.1  christos   memset (hdr, 0, sizeof (struct external_filehdr));
    592  1.1  christos 
    593  1.1  christos   set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
    594  1.1  christos   set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns);
    595  1.1  christos   /* f_timdat left as zero.  */
    596  1.1  christos   if (u64)
    597  1.1  christos     {
    598  1.1  christos       set_64 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr),
    599  1.1  christos 	      symtab_offset);
    600  1.1  christos       set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms),
    601  1.1  christos 	      nsyms);
    602  1.1  christos       /* f_opthdr left as zero.  */
    603  1.1  christos       set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags),
    604  1.1  christos 	      attrs->flags);
    605  1.1  christos     }
    606  1.1  christos   else
    607  1.1  christos     {
    608  1.1  christos       set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr),
    609  1.1  christos 	      symtab_offset);
    610  1.1  christos       set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms),
    611  1.1  christos 	      nsyms);
    612  1.1  christos       /* f_opthdr left as zero.  */
    613  1.1  christos       set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags),
    614  1.1  christos 	      attrs->flags);
    615  1.1  christos     }
    616  1.1  christos 
    617  1.1  christos   return simple_object_internal_write (descriptor, 0, hdrbuf,
    618  1.1  christos 				       sizeof (struct external_filehdr),
    619  1.1  christos 				       errmsg, err);
    620  1.1  christos }
    621  1.1  christos 
    622  1.1  christos /* Write out a XCOFF section header.  */
    623  1.1  christos 
    624  1.1  christos static int
    625  1.1  christos simple_object_xcoff_write_scnhdr (simple_object_write *sobj,
    626  1.1  christos 				  int descriptor,
    627  1.1  christos 				  const char *name, size_t *name_offset,
    628  1.1  christos 				  off_t scnhdr_offset, size_t scnsize,
    629  1.1  christos 				  off_t offset, unsigned int align,
    630  1.1  christos 				  const char **errmsg, int *err)
    631  1.1  christos {
    632  1.1  christos   struct simple_object_xcoff_read *ocr =
    633  1.1  christos     (struct simple_object_xcoff_read *) sobj->data;
    634  1.1  christos   int u64 = ocr->magic == U64_TOCMAGIC;
    635  1.1  christos   void (*set_32) (unsigned char *, unsigned int);
    636  1.1  christos   void (*set_64) (unsigned char *, unsigned int);
    637  1.1  christos   unsigned char hdrbuf[sizeof (struct external_scnhdr)];
    638  1.1  christos   unsigned char *hdr;
    639  1.1  christos   size_t namelen;
    640  1.1  christos   unsigned int flags;
    641  1.1  christos 
    642  1.1  christos   set_32 = simple_object_set_big_32;
    643  1.1  christos   set_64 = simple_object_set_big_32;
    644  1.1  christos 
    645  1.1  christos   memset (hdrbuf, 0, sizeof hdrbuf);
    646  1.1  christos   hdr = &hdrbuf[0];
    647  1.1  christos 
    648  1.1  christos   namelen = strlen (name);
    649  1.1  christos   if (namelen <= SCNNMLEN)
    650  1.1  christos     strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name),
    651  1.1  christos 	     name, SCNNMLEN);
    652  1.1  christos   else
    653  1.1  christos     {
    654  1.1  christos       snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name),
    655  1.1  christos 		SCNNMLEN, "/%lu", (unsigned long) *name_offset);
    656  1.1  christos       *name_offset += namelen + 1;
    657  1.1  christos     }
    658  1.1  christos 
    659  1.1  christos   /* s_paddr left as zero.  */
    660  1.1  christos   /* s_vaddr left as zero.  */
    661  1.1  christos   if (u64)
    662  1.1  christos     {
    663  1.1  christos       set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_size),
    664  1.1  christos 	      scnsize);
    665  1.1  christos       set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_scnptr),
    666  1.1  christos 	      offset);
    667  1.1  christos     }
    668  1.1  christos   else
    669  1.1  christos     {
    670  1.1  christos       set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_size),
    671  1.1  christos 	      scnsize);
    672  1.1  christos       set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_scnptr),
    673  1.1  christos 	      offset);
    674  1.1  christos     }
    675  1.1  christos   /* s_relptr left as zero.  */
    676  1.1  christos   /* s_lnnoptr left as zero.  */
    677  1.1  christos   /* s_nreloc left as zero.  */
    678  1.1  christos   /* s_nlnno left as zero.  */
    679  1.1  christos   flags = STYP_DATA;
    680  1.1  christos   if (align > 13)
    681  1.1  christos     align = 13;
    682  1.1  christos   if (u64)
    683  1.1  christos     set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_flags), flags);
    684  1.1  christos   else
    685  1.1  christos     set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_flags), flags);
    686  1.1  christos 
    687  1.1  christos   return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf,
    688  1.1  christos 				       u64 ? SCNHSZ64 : SCNHSZ32,
    689  1.1  christos 				       errmsg, err);
    690  1.1  christos }
    691  1.1  christos 
    692  1.1  christos /* Write out a complete XCOFF file.  */
    693  1.1  christos 
    694  1.1  christos static const char *
    695  1.1  christos simple_object_xcoff_write_to_file (simple_object_write *sobj, int descriptor,
    696  1.1  christos 				  int *err)
    697  1.1  christos {
    698  1.1  christos   struct simple_object_xcoff_read *ocr =
    699  1.1  christos     (struct simple_object_xcoff_read *) sobj->data;
    700  1.1  christos   int u64 = ocr->magic == U64_TOCMAGIC;
    701  1.1  christos   unsigned int nscns, secnum;
    702  1.1  christos   simple_object_write_section *section;
    703  1.1  christos   off_t scnhdr_offset;
    704  1.1  christos   size_t symtab_offset;
    705  1.1  christos   off_t secsym_offset;
    706  1.1  christos   unsigned int nsyms;
    707  1.1  christos   size_t offset;
    708  1.1  christos   size_t name_offset;
    709  1.1  christos   const char *errmsg;
    710  1.1  christos   unsigned char strsizebuf[4];
    711  1.1  christos   /* The interface doesn't give us access to the name of the input file
    712  1.1  christos      yet.  We want to use its basename for the FILE symbol.  This is
    713  1.1  christos      what 'gas' uses when told to assemble from stdin.  */
    714  1.1  christos   const char *source_filename = "fake";
    715  1.1  christos   size_t sflen;
    716  1.1  christos   union
    717  1.1  christos   {
    718  1.1  christos     struct external_syment sym;
    719  1.1  christos     union external_auxent aux;
    720  1.1  christos   } syms[2];
    721  1.1  christos   void (*set_16) (unsigned char *, unsigned short);
    722  1.1  christos   void (*set_32) (unsigned char *, unsigned int);
    723  1.1  christos 
    724  1.1  christos   set_16 = simple_object_set_big_16;
    725  1.1  christos   set_32 = simple_object_set_big_32;
    726  1.1  christos 
    727  1.1  christos   nscns = 0;
    728  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    729  1.1  christos     ++nscns;
    730  1.1  christos 
    731  1.1  christos   scnhdr_offset = sizeof (struct external_filehdr) - (u64 ? 4 : 0);
    732  1.1  christos   offset = scnhdr_offset + nscns * (u64 ? SCNHSZ64 : SCNHSZ32);
    733  1.1  christos   name_offset = 4;
    734  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    735  1.1  christos     {
    736  1.1  christos       size_t mask;
    737  1.1  christos       size_t new_offset;
    738  1.1  christos       size_t scnsize;
    739  1.1  christos       struct simple_object_write_section_buffer *buffer;
    740  1.1  christos 
    741  1.1  christos       mask = (1U << section->align) - 1;
    742  1.1  christos       new_offset = offset & mask;
    743  1.1  christos       new_offset &= ~ mask;
    744  1.1  christos       while (new_offset > offset)
    745  1.1  christos 	{
    746  1.1  christos 	  unsigned char zeroes[16];
    747  1.1  christos 	  size_t write;
    748  1.1  christos 
    749  1.1  christos 	  memset (zeroes, 0, sizeof zeroes);
    750  1.1  christos 	  write = new_offset - offset;
    751  1.1  christos 	  if (write > sizeof zeroes)
    752  1.1  christos 	    write = sizeof zeroes;
    753  1.1  christos 	  if (!simple_object_internal_write (descriptor, offset, zeroes, write,
    754  1.1  christos 					     &errmsg, err))
    755  1.1  christos 	    return errmsg;
    756  1.1  christos 	}
    757  1.1  christos 
    758  1.1  christos       scnsize = 0;
    759  1.1  christos       for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
    760  1.1  christos 	{
    761  1.1  christos 	  if (!simple_object_internal_write (descriptor, offset + scnsize,
    762  1.1  christos 					     ((const unsigned char *)
    763  1.1  christos 					      buffer->buffer),
    764  1.1  christos 					     buffer->size, &errmsg, err))
    765  1.1  christos 	    return errmsg;
    766  1.1  christos 	  scnsize += buffer->size;
    767  1.1  christos 	}
    768  1.1  christos 
    769  1.1  christos       if (!simple_object_xcoff_write_scnhdr (sobj, descriptor, section->name,
    770  1.1  christos 					    &name_offset, scnhdr_offset,
    771  1.1  christos 					    scnsize, offset, section->align,
    772  1.1  christos 					    &errmsg, err))
    773  1.1  christos 	return errmsg;
    774  1.1  christos 
    775  1.1  christos       scnhdr_offset += u64 ? SCNHSZ64 : SCNHSZ32;
    776  1.1  christos       offset += scnsize;
    777  1.1  christos     }
    778  1.1  christos 
    779  1.1  christos   /* Symbol table is always half-word aligned.  */
    780  1.1  christos   offset += (offset & 1);
    781  1.1  christos   /* There is a file symbol and a section symbol per section,
    782  1.1  christos      and each of these has a single auxiliary symbol following.  */
    783  1.1  christos   nsyms = 2 * (nscns + 1);
    784  1.1  christos   symtab_offset = offset;
    785  1.1  christos   /* Advance across space reserved for symbol table to locate
    786  1.1  christos      start of string table.  */
    787  1.1  christos   offset += nsyms * SYMESZ;
    788  1.1  christos 
    789  1.1  christos   /* Write out file symbol.  */
    790  1.1  christos   memset (&syms[0], 0, sizeof (syms));
    791  1.1  christos   if (!u64)
    792  1.1  christos     strcpy ((char *)&syms[0].sym.u.xcoff32.n.n_name[0], ".file");
    793  1.1  christos   set_16 (&syms[0].sym.n_scnum[0], N_DEBUG);
    794  1.1  christos   set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE);
    795  1.1  christos   syms[0].sym.n_sclass[0] = C_FILE;
    796  1.1  christos   syms[0].sym.n_numaux[0] = 1;
    797  1.1  christos   /* The name need not be nul-terminated if it fits into the x_fname field
    798  1.1  christos      directly, but must be if it has to be placed into the string table.  */
    799  1.1  christos   sflen = strlen (source_filename);
    800  1.1  christos   if (sflen <= FILNMLEN)
    801  1.1  christos     memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
    802  1.1  christos   else
    803  1.1  christos     {
    804  1.1  christos       set_32 (&syms[1].aux.x_file._x.x_offset[0], name_offset);
    805  1.1  christos       if (!simple_object_internal_write (descriptor, offset + name_offset,
    806  1.1  christos 					 ((const unsigned char *)
    807  1.1  christos 					  source_filename),
    808  1.1  christos 					 sflen + 1, &errmsg, err))
    809  1.1  christos 	return errmsg;
    810  1.1  christos       name_offset += strlen (source_filename) + 1;
    811  1.1  christos     }
    812  1.1  christos   if (!simple_object_internal_write (descriptor, symtab_offset,
    813  1.1  christos 				     (const unsigned char *) &syms[0],
    814  1.1  christos 				     sizeof (syms), &errmsg, err))
    815  1.1  christos     return errmsg;
    816  1.1  christos 
    817  1.1  christos   /* Write the string table length, followed by the strings and section
    818  1.1  christos      symbols in step with each other.  */
    819  1.1  christos   set_32 (strsizebuf, name_offset);
    820  1.1  christos   if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
    821  1.1  christos 				     &errmsg, err))
    822  1.1  christos     return errmsg;
    823  1.1  christos 
    824  1.1  christos   name_offset = 4;
    825  1.1  christos   secsym_offset = symtab_offset + sizeof (syms);
    826  1.1  christos   memset (&syms[0], 0, sizeof (syms));
    827  1.1  christos   set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE);
    828  1.1  christos   syms[0].sym.n_sclass[0] = C_STAT;
    829  1.1  christos   syms[0].sym.n_numaux[0] = 1;
    830  1.1  christos   secnum = 1;
    831  1.1  christos 
    832  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    833  1.1  christos     {
    834  1.1  christos       size_t namelen;
    835  1.1  christos       size_t scnsize;
    836  1.1  christos       struct simple_object_write_section_buffer *buffer;
    837  1.1  christos 
    838  1.1  christos       namelen = strlen (section->name);
    839  1.1  christos       set_16 (&syms[0].sym.n_scnum[0], secnum++);
    840  1.1  christos       scnsize = 0;
    841  1.1  christos       for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
    842  1.1  christos 	scnsize += buffer->size;
    843  1.1  christos       set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
    844  1.1  christos       if (namelen > SCNNMLEN)
    845  1.1  christos 	{
    846  1.1  christos 	  set_32 (&syms[0].sym.u.xcoff32.n.n.n_zeroes[0], 0);
    847  1.1  christos 	  set_32 (&syms[0].sym.u.xcoff32.n.n.n_offset[0], name_offset);
    848  1.1  christos 	  if (!simple_object_internal_write (descriptor, offset + name_offset,
    849  1.1  christos 					     ((const unsigned char *)
    850  1.1  christos 					      section->name),
    851  1.1  christos 					     namelen + 1, &errmsg, err))
    852  1.1  christos 	    return errmsg;
    853  1.1  christos 	  name_offset += namelen + 1;
    854  1.1  christos 	}
    855  1.1  christos       else
    856  1.1  christos 	{
    857  1.1  christos 	  memcpy (&syms[0].sym.u.xcoff32.n.n_name[0], section->name,
    858  1.1  christos 		  strlen (section->name));
    859  1.1  christos 	  memset (&syms[0].sym.u.xcoff32.n.n_name[strlen (section->name)], 0,
    860  1.1  christos 		  N_SYMNMLEN - strlen (section->name));
    861  1.1  christos 	}
    862  1.1  christos 
    863  1.1  christos       if (!simple_object_internal_write (descriptor, secsym_offset,
    864  1.1  christos 					 (const unsigned char *) &syms[0],
    865  1.1  christos 					 sizeof (syms), &errmsg, err))
    866  1.1  christos 	return errmsg;
    867  1.1  christos       secsym_offset += sizeof (syms);
    868  1.1  christos     }
    869  1.1  christos 
    870  1.1  christos   if (!simple_object_xcoff_write_filehdr (sobj, descriptor, nscns,
    871  1.1  christos 					 symtab_offset, nsyms, &errmsg, err))
    872  1.1  christos     return errmsg;
    873  1.1  christos 
    874  1.1  christos   return NULL;
    875  1.1  christos }
    876  1.1  christos 
    877  1.1  christos /* Release the private data for an simple_object_write structure.  */
    878  1.1  christos 
    879  1.1  christos static void
    880  1.1  christos simple_object_xcoff_release_write (void *data)
    881  1.1  christos {
    882  1.1  christos   XDELETE (data);
    883  1.1  christos }
    884  1.1  christos 
    885  1.1  christos /* The XCOFF functions.  */
    886  1.1  christos 
    887  1.1  christos const struct simple_object_functions simple_object_xcoff_functions =
    888  1.1  christos {
    889  1.1  christos   simple_object_xcoff_match,
    890  1.1  christos   simple_object_xcoff_find_sections,
    891  1.1  christos   simple_object_xcoff_fetch_attributes,
    892  1.1  christos   simple_object_xcoff_release_read,
    893  1.1  christos   simple_object_xcoff_attributes_merge,
    894  1.1  christos   simple_object_xcoff_release_attributes,
    895  1.1  christos   simple_object_xcoff_start_write,
    896  1.1  christos   simple_object_xcoff_write_to_file,
    897  1.1  christos   simple_object_xcoff_release_write
    898  1.1  christos };
    899