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