simple-object-xcoff.c revision 1.1.1.2.2.1 1 1.1 christos /* simple-object-coff.c -- routines to manipulate XCOFF object files.
2 1.1.1.2 christos Copyright (C) 2013-2018 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.1.2 christos /* The name of the symbol. There is an implicit null character
142 1.1.1.2 christos after the end of the array. */
143 1.1.1.2 christos char n_name[N_SYMNMLEN];
144 1.1.1.2 christos struct {
145 1.1.1.2 christos /* If n_zeroes is zero, n_offset is the offset the name from
146 1.1.1.2 christos the start of the string table. */
147 1.1.1.2 christos unsigned char n_zeroes[4];
148 1.1.1.2 christos unsigned char n_offset[4];
149 1.1.1.2 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.1.2 christos #define C_EXT (2)
259 1.1 christos #define C_STAT (3)
260 1.1 christos #define C_FILE (103)
261 1.1.1.2 christos #define C_HIDEXT (107)
262 1.1.1.2 christos
263 1.1.1.2 christos #define XTY_SD (1) /* section definition */
264 1.1.1.2 christos
265 1.1.1.2 christos #define XMC_XO (7) /* extended operation */
266 1.1 christos
267 1.1 christos /* Private data for an simple_object_read. */
268 1.1 christos
269 1.1 christos struct simple_object_xcoff_read
270 1.1 christos {
271 1.1 christos /* Magic number. */
272 1.1 christos unsigned short magic;
273 1.1 christos /* Number of sections. */
274 1.1 christos unsigned short nscns;
275 1.1 christos /* File offset of symbol table. */
276 1.1 christos off_t symptr;
277 1.1 christos /* Number of symbol table entries. */
278 1.1 christos unsigned int nsyms;
279 1.1 christos /* Flags. */
280 1.1 christos unsigned short flags;
281 1.1 christos /* Offset of section headers in file. */
282 1.1 christos off_t scnhdr_offset;
283 1.1 christos };
284 1.1 christos
285 1.1 christos /* Private data for an simple_object_attributes. */
286 1.1 christos
287 1.1 christos struct simple_object_xcoff_attributes
288 1.1 christos {
289 1.1 christos /* Magic number. */
290 1.1 christos unsigned short magic;
291 1.1 christos /* Flags. */
292 1.1 christos unsigned short flags;
293 1.1 christos };
294 1.1 christos
295 1.1 christos /* See if we have a XCOFF file. */
296 1.1 christos
297 1.1 christos static void *
298 1.1 christos simple_object_xcoff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
299 1.1 christos int descriptor, off_t offset,
300 1.1 christos const char *segment_name ATTRIBUTE_UNUSED,
301 1.1 christos const char **errmsg, int *err)
302 1.1 christos {
303 1.1 christos unsigned short magic;
304 1.1 christos unsigned short (*fetch_16) (const unsigned char *);
305 1.1 christos unsigned int (*fetch_32) (const unsigned char *);
306 1.1 christos ulong_type (*fetch_64) (const unsigned char *);
307 1.1 christos unsigned char hdrbuf[sizeof (struct external_filehdr)];
308 1.1 christos struct simple_object_xcoff_read *ocr;
309 1.1 christos int u64;
310 1.1 christos
311 1.1 christos magic = simple_object_fetch_big_16 (header);
312 1.1 christos
313 1.1 christos if (magic != U802TOCMAGIC && magic != U64_TOCMAGIC)
314 1.1 christos {
315 1.1 christos *errmsg = NULL;
316 1.1 christos *err = 0;
317 1.1 christos return NULL;
318 1.1 christos }
319 1.1 christos
320 1.1 christos fetch_16 = simple_object_fetch_big_16;
321 1.1 christos fetch_32 = simple_object_fetch_big_32;
322 1.1 christos fetch_64 = simple_object_fetch_big_64;
323 1.1 christos
324 1.1 christos if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
325 1.1 christos errmsg, err))
326 1.1 christos return NULL;
327 1.1 christos
328 1.1 christos u64 = magic == U64_TOCMAGIC;
329 1.1 christos
330 1.1 christos ocr = XNEW (struct simple_object_xcoff_read);
331 1.1 christos ocr->magic = magic;
332 1.1 christos ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
333 1.1 christos if (u64)
334 1.1 christos {
335 1.1 christos ocr->symptr = fetch_64 (hdrbuf
336 1.1 christos + offsetof (struct external_filehdr,
337 1.1 christos u.xcoff64.f_symptr));
338 1.1 christos ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr,
339 1.1 christos u.xcoff64.f_nsyms));
340 1.1 christos ocr->scnhdr_offset = (sizeof (struct external_filehdr)
341 1.1 christos + fetch_16 (hdrbuf + offsetof (struct external_filehdr,
342 1.1 christos u.xcoff64.f_opthdr)));
343 1.1 christos
344 1.1 christos }
345 1.1 christos else
346 1.1 christos {
347 1.1 christos ocr->symptr = fetch_32 (hdrbuf
348 1.1 christos + offsetof (struct external_filehdr,
349 1.1 christos u.xcoff32.f_symptr));
350 1.1 christos ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr,
351 1.1 christos u.xcoff32.f_nsyms));
352 1.1 christos ocr->scnhdr_offset = (sizeof (struct external_filehdr) - 4
353 1.1 christos + fetch_16 (hdrbuf + offsetof (struct external_filehdr,
354 1.1 christos u.xcoff32.f_opthdr)));
355 1.1 christos
356 1.1 christos }
357 1.1 christos
358 1.1 christos return (void *) ocr;
359 1.1 christos }
360 1.1 christos
361 1.1 christos /* Read the string table in a XCOFF file. */
362 1.1 christos
363 1.1 christos static char *
364 1.1 christos simple_object_xcoff_read_strtab (simple_object_read *sobj, size_t *strtab_size,
365 1.1 christos const char **errmsg, int *err)
366 1.1 christos {
367 1.1 christos struct simple_object_xcoff_read *ocr =
368 1.1 christos (struct simple_object_xcoff_read *) sobj->data;
369 1.1 christos off_t strtab_offset;
370 1.1 christos unsigned char strsizebuf[4];
371 1.1 christos size_t strsize;
372 1.1 christos char *strtab;
373 1.1 christos
374 1.1 christos strtab_offset = sobj->offset + ocr->symptr
375 1.1 christos + ocr->nsyms * SYMESZ;
376 1.1 christos if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
377 1.1 christos strsizebuf, 4, errmsg, err))
378 1.1 christos return NULL;
379 1.1 christos strsize = simple_object_fetch_big_32 (strsizebuf);
380 1.1 christos strtab = XNEWVEC (char, strsize);
381 1.1 christos if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
382 1.1 christos (unsigned char *) strtab, strsize, errmsg,
383 1.1 christos err))
384 1.1 christos {
385 1.1 christos XDELETEVEC (strtab);
386 1.1 christos return NULL;
387 1.1 christos }
388 1.1 christos *strtab_size = strsize;
389 1.1 christos return strtab;
390 1.1 christos }
391 1.1 christos
392 1.1 christos /* Find all sections in a XCOFF file. */
393 1.1 christos
394 1.1 christos static const char *
395 1.1 christos simple_object_xcoff_find_sections (simple_object_read *sobj,
396 1.1 christos int (*pfn) (void *, const char *,
397 1.1 christos off_t offset, off_t length),
398 1.1 christos void *data,
399 1.1 christos int *err)
400 1.1 christos {
401 1.1 christos struct simple_object_xcoff_read *ocr =
402 1.1 christos (struct simple_object_xcoff_read *) sobj->data;
403 1.1 christos int u64 = ocr->magic == U64_TOCMAGIC;
404 1.1 christos size_t scnhdr_size;
405 1.1 christos unsigned char *scnbuf;
406 1.1 christos const char *errmsg;
407 1.1.1.2 christos unsigned short (*fetch_16) (const unsigned char *);
408 1.1 christos unsigned int (*fetch_32) (const unsigned char *);
409 1.1 christos ulong_type (*fetch_64) (const unsigned char *);
410 1.1 christos unsigned int nscns;
411 1.1 christos char *strtab;
412 1.1 christos size_t strtab_size;
413 1.1.1.2 christos struct external_syment *symtab = NULL;
414 1.1 christos unsigned int i;
415 1.1 christos
416 1.1 christos scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32;
417 1.1 christos scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns);
418 1.1 christos if (!simple_object_internal_read (sobj->descriptor,
419 1.1 christos sobj->offset + ocr->scnhdr_offset,
420 1.1 christos scnbuf, scnhdr_size * ocr->nscns, &errmsg,
421 1.1 christos err))
422 1.1 christos {
423 1.1 christos XDELETEVEC (scnbuf);
424 1.1 christos return errmsg;
425 1.1 christos }
426 1.1 christos
427 1.1.1.2 christos fetch_16 = simple_object_fetch_big_16;
428 1.1 christos fetch_32 = simple_object_fetch_big_32;
429 1.1 christos fetch_64 = simple_object_fetch_big_64;
430 1.1 christos
431 1.1 christos nscns = ocr->nscns;
432 1.1 christos strtab = NULL;
433 1.1 christos strtab_size = 0;
434 1.1 christos for (i = 0; i < nscns; ++i)
435 1.1 christos {
436 1.1 christos unsigned char *scnhdr;
437 1.1 christos unsigned char *scnname;
438 1.1 christos char namebuf[SCNNMLEN + 1];
439 1.1 christos char *name;
440 1.1 christos off_t scnptr;
441 1.1.1.2 christos off_t size;
442 1.1 christos
443 1.1 christos scnhdr = scnbuf + i * scnhdr_size;
444 1.1 christos scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
445 1.1 christos memcpy (namebuf, scnname, SCNNMLEN);
446 1.1 christos namebuf[SCNNMLEN] = '\0';
447 1.1 christos name = &namebuf[0];
448 1.1 christos if (namebuf[0] == '/')
449 1.1 christos {
450 1.1 christos size_t strindex;
451 1.1 christos char *end;
452 1.1 christos
453 1.1 christos strindex = strtol (namebuf + 1, &end, 10);
454 1.1 christos if (*end == '\0')
455 1.1 christos {
456 1.1 christos /* The real section name is found in the string
457 1.1 christos table. */
458 1.1 christos if (strtab == NULL)
459 1.1 christos {
460 1.1 christos strtab = simple_object_xcoff_read_strtab (sobj,
461 1.1 christos &strtab_size,
462 1.1 christos &errmsg, err);
463 1.1 christos if (strtab == NULL)
464 1.1 christos {
465 1.1 christos XDELETEVEC (scnbuf);
466 1.1 christos return errmsg;
467 1.1 christos }
468 1.1 christos }
469 1.1 christos
470 1.1 christos if (strindex < 4 || strindex >= strtab_size)
471 1.1 christos {
472 1.1 christos XDELETEVEC (strtab);
473 1.1 christos XDELETEVEC (scnbuf);
474 1.1 christos *err = 0;
475 1.1 christos return "section string index out of range";
476 1.1 christos }
477 1.1 christos
478 1.1 christos name = strtab + strindex;
479 1.1 christos }
480 1.1 christos }
481 1.1 christos
482 1.1 christos if (u64)
483 1.1 christos {
484 1.1 christos scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
485 1.1 christos u.xcoff64.s_scnptr));
486 1.1 christos size = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
487 1.1 christos u.xcoff64.s_size));
488 1.1 christos }
489 1.1 christos else
490 1.1 christos {
491 1.1 christos scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
492 1.1 christos u.xcoff32.s_scnptr));
493 1.1 christos size = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
494 1.1 christos u.xcoff32.s_size));
495 1.1 christos }
496 1.1 christos
497 1.1 christos if (!(*pfn) (data, name, scnptr, size))
498 1.1 christos break;
499 1.1 christos }
500 1.1 christos
501 1.1.1.2 christos /* Special handling for .go_export csect. */
502 1.1.1.2 christos if (ocr->nsyms > 0)
503 1.1.1.2 christos {
504 1.1.1.2 christos unsigned char *sym;
505 1.1.1.2 christos const char *n_name;
506 1.1.1.2 christos off_t size, n_value;
507 1.1.1.2 christos unsigned int n_numaux, n_offset, n_zeroes;
508 1.1.1.2 christos short n_scnum;
509 1.1.1.2 christos
510 1.1.1.2 christos /* Read symbol table. */
511 1.1.1.2 christos symtab = XNEWVEC (struct external_syment, ocr->nsyms * SYMESZ);
512 1.1.1.2 christos if (!simple_object_internal_read (sobj->descriptor,
513 1.1.1.2 christos sobj->offset + ocr->symptr,
514 1.1.1.2 christos (unsigned char *) symtab,
515 1.1.1.2 christos ocr->nsyms * SYMESZ,
516 1.1.1.2 christos &errmsg, err))
517 1.1.1.2 christos {
518 1.1.1.2 christos XDELETEVEC (symtab);
519 1.1.1.2 christos XDELETEVEC (scnbuf);
520 1.1.1.2 christos return NULL;
521 1.1.1.2 christos }
522 1.1.1.2 christos
523 1.1.1.2 christos /* Search in symbol table if we have a ".go_export" symbol. */
524 1.1.1.2 christos for (i = 0; i < ocr->nsyms; i += n_numaux + 1)
525 1.1.1.2 christos {
526 1.1.1.2 christos sym = (unsigned char *) &symtab[i];
527 1.1.1.2 christos n_numaux = symtab[i].n_numaux[0];
528 1.1.1.2 christos
529 1.1.1.2 christos if (symtab[i].n_sclass[0] != C_EXT
530 1.1.1.2 christos && symtab[i].n_sclass[0] != C_HIDEXT)
531 1.1.1.2 christos continue;
532 1.1.1.2 christos
533 1.1.1.2 christos /* Must have at least one csect auxiliary entry. */
534 1.1.1.2 christos if (n_numaux < 1 || i + n_numaux >= ocr->nsyms)
535 1.1.1.2 christos continue;
536 1.1.1.2 christos
537 1.1.1.2 christos n_scnum = fetch_16 (sym + offsetof (struct external_syment,
538 1.1.1.2 christos n_scnum));
539 1.1.1.2 christos if (n_scnum < 1 || (unsigned int) n_scnum > nscns)
540 1.1.1.2 christos continue;
541 1.1.1.2 christos
542 1.1.1.2 christos if (u64)
543 1.1.1.2 christos {
544 1.1.1.2 christos n_value = fetch_64 (sym + offsetof (struct external_syment,
545 1.1.1.2 christos u.xcoff64.n_value));
546 1.1.1.2 christos n_offset = fetch_32 (sym + offsetof (struct external_syment,
547 1.1.1.2 christos u.xcoff64.n_offset));
548 1.1.1.2 christos }
549 1.1.1.2 christos else
550 1.1.1.2 christos {
551 1.1.1.2 christos /* ".go_export" is longer than N_SYMNMLEN. */
552 1.1.1.2 christos n_zeroes = fetch_32 (sym + offsetof (struct external_syment,
553 1.1.1.2 christos u.xcoff32.n.n.n_zeroes));
554 1.1.1.2 christos if (n_zeroes != 0)
555 1.1.1.2 christos continue;
556 1.1.1.2 christos
557 1.1.1.2 christos n_value = fetch_32 (sym + offsetof (struct external_syment,
558 1.1.1.2 christos u.xcoff32.n_value));
559 1.1.1.2 christos n_offset = fetch_32 (sym + offsetof (struct external_syment,
560 1.1.1.2 christos u.xcoff32.n.n.n_offset));
561 1.1.1.2 christos }
562 1.1.1.2 christos
563 1.1.1.2 christos /* The real symbol name is found in the string table. */
564 1.1.1.2 christos if (strtab == NULL)
565 1.1.1.2 christos {
566 1.1.1.2 christos strtab = simple_object_xcoff_read_strtab (sobj,
567 1.1.1.2 christos &strtab_size,
568 1.1.1.2 christos &errmsg, err);
569 1.1.1.2 christos if (strtab == NULL)
570 1.1.1.2 christos {
571 1.1.1.2 christos XDELETEVEC (symtab);
572 1.1.1.2 christos XDELETEVEC (scnbuf);
573 1.1.1.2 christos return errmsg;
574 1.1.1.2 christos }
575 1.1.1.2 christos }
576 1.1.1.2 christos
577 1.1.1.2 christos if (n_offset >= strtab_size)
578 1.1.1.2 christos {
579 1.1.1.2 christos XDELETEVEC (strtab);
580 1.1.1.2 christos XDELETEVEC (symtab);
581 1.1.1.2 christos XDELETEVEC (scnbuf);
582 1.1.1.2 christos *err = 0;
583 1.1.1.2 christos return "symbol string index out of range";
584 1.1.1.2 christos }
585 1.1.1.2 christos n_name = strtab + n_offset;
586 1.1.1.2 christos
587 1.1.1.2 christos if (!strcmp (n_name, ".go_export"))
588 1.1.1.2 christos {
589 1.1.1.2 christos union external_auxent *auxent;
590 1.1.1.2 christos unsigned char *aux, *scnhdr;
591 1.1.1.2 christos off_t scnptr, x_scnlen;
592 1.1.1.2 christos
593 1.1.1.2 christos /* Found .go_export symbol, read its csect auxiliary entry.
594 1.1.1.2 christos By convention, it is the last auxiliary entry. */
595 1.1.1.2 christos auxent = (union external_auxent *) &symtab[i + n_numaux];
596 1.1.1.2 christos aux = (unsigned char *) auxent;
597 1.1.1.2 christos if (u64)
598 1.1.1.2 christos {
599 1.1.1.2.2.1 christos /* Use an intermediate 64-bit type to avoid
600 1.1.1.2.2.1 christos compilation warning about 32-bit shift below on
601 1.1.1.2.2.1 christos hosts with 32-bit off_t which aren't supported by
602 1.1.1.2.2.1 christos AC_SYS_LARGEFILE. */
603 1.1.1.2.2.1 christos ulong_type x_scnlen64;
604 1.1.1.2.2.1 christos
605 1.1.1.2 christos if ((auxent->u.xcoff64.x_csect.x_smtyp & 0x7) != XTY_SD
606 1.1.1.2 christos || auxent->u.xcoff64.x_csect.x_smclas != XMC_XO)
607 1.1.1.2 christos continue;
608 1.1.1.2 christos
609 1.1.1.2.2.1 christos x_scnlen64 =
610 1.1.1.2.2.1 christos fetch_32 (aux + offsetof (union external_auxent,
611 1.1.1.2.2.1 christos u.xcoff64.x_csect.x_scnlen_hi));
612 1.1.1.2.2.1 christos x_scnlen =
613 1.1.1.2.2.1 christos ((x_scnlen64 << 32)
614 1.1.1.2.2.1 christos | fetch_32 (aux
615 1.1.1.2.2.1 christos + offsetof (union external_auxent,
616 1.1.1.2.2.1 christos u.xcoff64.x_csect.x_scnlen_lo)));
617 1.1.1.2 christos }
618 1.1.1.2 christos else
619 1.1.1.2 christos {
620 1.1.1.2 christos if ((auxent->u.xcoff32.x_csect.x_smtyp & 0x7) != XTY_SD
621 1.1.1.2 christos || auxent->u.xcoff32.x_csect.x_smclas != XMC_XO)
622 1.1.1.2 christos continue;
623 1.1.1.2 christos
624 1.1.1.2 christos x_scnlen = fetch_32 (aux + offsetof (union external_auxent,
625 1.1.1.2 christos u.xcoff32.x_csect.x_scnlen));
626 1.1.1.2 christos }
627 1.1.1.2 christos
628 1.1.1.2 christos /* Get header of containing section. */
629 1.1.1.2 christos scnhdr = scnbuf + (n_scnum - 1) * scnhdr_size;
630 1.1.1.2 christos if (u64)
631 1.1.1.2 christos {
632 1.1.1.2 christos scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
633 1.1.1.2 christos u.xcoff64.s_scnptr));
634 1.1.1.2 christos size = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
635 1.1.1.2 christos u.xcoff64.s_size));
636 1.1.1.2 christos }
637 1.1.1.2 christos else
638 1.1.1.2 christos {
639 1.1.1.2 christos scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
640 1.1.1.2 christos u.xcoff32.s_scnptr));
641 1.1.1.2 christos size = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
642 1.1.1.2 christos u.xcoff32.s_size));
643 1.1.1.2 christos }
644 1.1.1.2 christos if (n_value + x_scnlen > size)
645 1.1.1.2 christos break;
646 1.1.1.2 christos
647 1.1.1.2 christos (*pfn) (data, ".go_export", scnptr + n_value, x_scnlen);
648 1.1.1.2 christos break;
649 1.1.1.2 christos }
650 1.1.1.2 christos }
651 1.1.1.2 christos }
652 1.1.1.2 christos
653 1.1.1.2 christos if (symtab != NULL)
654 1.1.1.2 christos XDELETEVEC (symtab);
655 1.1 christos if (strtab != NULL)
656 1.1 christos XDELETEVEC (strtab);
657 1.1 christos XDELETEVEC (scnbuf);
658 1.1 christos
659 1.1 christos return NULL;
660 1.1 christos }
661 1.1 christos
662 1.1 christos /* Fetch the attributes for an simple_object_read. */
663 1.1 christos
664 1.1 christos static void *
665 1.1 christos simple_object_xcoff_fetch_attributes (simple_object_read *sobj,
666 1.1 christos const char **errmsg ATTRIBUTE_UNUSED,
667 1.1 christos int *err ATTRIBUTE_UNUSED)
668 1.1 christos {
669 1.1 christos struct simple_object_xcoff_read *ocr =
670 1.1 christos (struct simple_object_xcoff_read *) sobj->data;
671 1.1 christos struct simple_object_xcoff_attributes *ret;
672 1.1 christos
673 1.1 christos ret = XNEW (struct simple_object_xcoff_attributes);
674 1.1 christos ret->magic = ocr->magic;
675 1.1 christos ret->flags = ocr->flags;
676 1.1 christos return ret;
677 1.1 christos }
678 1.1 christos
679 1.1 christos /* Release the private data for an simple_object_read. */
680 1.1 christos
681 1.1 christos static void
682 1.1 christos simple_object_xcoff_release_read (void *data)
683 1.1 christos {
684 1.1 christos XDELETE (data);
685 1.1 christos }
686 1.1 christos
687 1.1 christos /* Compare two attributes structures. */
688 1.1 christos
689 1.1 christos static const char *
690 1.1 christos simple_object_xcoff_attributes_merge (void *todata, void *fromdata, int *err)
691 1.1 christos {
692 1.1 christos struct simple_object_xcoff_attributes *to =
693 1.1 christos (struct simple_object_xcoff_attributes *) todata;
694 1.1 christos struct simple_object_xcoff_attributes *from =
695 1.1 christos (struct simple_object_xcoff_attributes *) fromdata;
696 1.1 christos
697 1.1 christos if (to->magic != from->magic)
698 1.1 christos {
699 1.1 christos *err = 0;
700 1.1 christos return "XCOFF object format mismatch";
701 1.1 christos }
702 1.1 christos return NULL;
703 1.1 christos }
704 1.1 christos
705 1.1 christos /* Release the private data for an attributes structure. */
706 1.1 christos
707 1.1 christos static void
708 1.1 christos simple_object_xcoff_release_attributes (void *data)
709 1.1 christos {
710 1.1 christos XDELETE (data);
711 1.1 christos }
712 1.1 christos
713 1.1 christos /* Prepare to write out a file. */
714 1.1 christos
715 1.1 christos static void *
716 1.1 christos simple_object_xcoff_start_write (void *attributes_data,
717 1.1 christos const char **errmsg ATTRIBUTE_UNUSED,
718 1.1 christos int *err ATTRIBUTE_UNUSED)
719 1.1 christos {
720 1.1 christos struct simple_object_xcoff_attributes *attrs =
721 1.1 christos (struct simple_object_xcoff_attributes *) attributes_data;
722 1.1 christos struct simple_object_xcoff_attributes *ret;
723 1.1 christos
724 1.1 christos /* We're just going to record the attributes, but we need to make a
725 1.1 christos copy because the user may delete them. */
726 1.1 christos ret = XNEW (struct simple_object_xcoff_attributes);
727 1.1 christos *ret = *attrs;
728 1.1 christos return ret;
729 1.1 christos }
730 1.1 christos
731 1.1 christos /* Write out a XCOFF filehdr. */
732 1.1 christos
733 1.1 christos static int
734 1.1 christos simple_object_xcoff_write_filehdr (simple_object_write *sobj, int descriptor,
735 1.1 christos unsigned int nscns, size_t symtab_offset,
736 1.1 christos unsigned int nsyms, const char **errmsg,
737 1.1 christos int *err)
738 1.1 christos {
739 1.1 christos struct simple_object_xcoff_attributes *attrs =
740 1.1 christos (struct simple_object_xcoff_attributes *) sobj->data;
741 1.1 christos int u64 = attrs->magic == U64_TOCMAGIC;
742 1.1 christos unsigned char hdrbuf[sizeof (struct external_filehdr)];
743 1.1 christos unsigned char *hdr;
744 1.1 christos void (*set_16) (unsigned char *, unsigned short);
745 1.1 christos void (*set_32) (unsigned char *, unsigned int);
746 1.1 christos void (*set_64) (unsigned char *, ulong_type);
747 1.1 christos
748 1.1 christos hdr = &hdrbuf[0];
749 1.1 christos
750 1.1 christos set_16 = simple_object_set_big_16;
751 1.1 christos set_32 = simple_object_set_big_32;
752 1.1 christos set_64 = simple_object_set_big_64;
753 1.1 christos
754 1.1 christos memset (hdr, 0, sizeof (struct external_filehdr));
755 1.1 christos
756 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
757 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns);
758 1.1 christos /* f_timdat left as zero. */
759 1.1 christos if (u64)
760 1.1 christos {
761 1.1 christos set_64 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr),
762 1.1 christos symtab_offset);
763 1.1 christos set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms),
764 1.1 christos nsyms);
765 1.1 christos /* f_opthdr left as zero. */
766 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags),
767 1.1 christos attrs->flags);
768 1.1 christos }
769 1.1 christos else
770 1.1 christos {
771 1.1 christos set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr),
772 1.1 christos symtab_offset);
773 1.1 christos set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms),
774 1.1 christos nsyms);
775 1.1 christos /* f_opthdr left as zero. */
776 1.1 christos set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags),
777 1.1 christos attrs->flags);
778 1.1 christos }
779 1.1 christos
780 1.1 christos return simple_object_internal_write (descriptor, 0, hdrbuf,
781 1.1 christos sizeof (struct external_filehdr),
782 1.1 christos errmsg, err);
783 1.1 christos }
784 1.1 christos
785 1.1 christos /* Write out a XCOFF section header. */
786 1.1 christos
787 1.1 christos static int
788 1.1 christos simple_object_xcoff_write_scnhdr (simple_object_write *sobj,
789 1.1 christos int descriptor,
790 1.1 christos const char *name, size_t *name_offset,
791 1.1 christos off_t scnhdr_offset, size_t scnsize,
792 1.1 christos off_t offset, unsigned int align,
793 1.1 christos const char **errmsg, int *err)
794 1.1 christos {
795 1.1 christos struct simple_object_xcoff_read *ocr =
796 1.1 christos (struct simple_object_xcoff_read *) sobj->data;
797 1.1 christos int u64 = ocr->magic == U64_TOCMAGIC;
798 1.1 christos void (*set_32) (unsigned char *, unsigned int);
799 1.1 christos void (*set_64) (unsigned char *, unsigned int);
800 1.1 christos unsigned char hdrbuf[sizeof (struct external_scnhdr)];
801 1.1 christos unsigned char *hdr;
802 1.1 christos size_t namelen;
803 1.1 christos unsigned int flags;
804 1.1 christos
805 1.1 christos set_32 = simple_object_set_big_32;
806 1.1 christos set_64 = simple_object_set_big_32;
807 1.1 christos
808 1.1 christos memset (hdrbuf, 0, sizeof hdrbuf);
809 1.1 christos hdr = &hdrbuf[0];
810 1.1 christos
811 1.1 christos namelen = strlen (name);
812 1.1 christos if (namelen <= SCNNMLEN)
813 1.1 christos strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name),
814 1.1 christos name, SCNNMLEN);
815 1.1 christos else
816 1.1 christos {
817 1.1 christos snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name),
818 1.1 christos SCNNMLEN, "/%lu", (unsigned long) *name_offset);
819 1.1 christos *name_offset += namelen + 1;
820 1.1 christos }
821 1.1 christos
822 1.1 christos /* s_paddr left as zero. */
823 1.1 christos /* s_vaddr left as zero. */
824 1.1 christos if (u64)
825 1.1 christos {
826 1.1 christos set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_size),
827 1.1 christos scnsize);
828 1.1 christos set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_scnptr),
829 1.1 christos offset);
830 1.1 christos }
831 1.1 christos else
832 1.1 christos {
833 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_size),
834 1.1 christos scnsize);
835 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_scnptr),
836 1.1 christos offset);
837 1.1 christos }
838 1.1 christos /* s_relptr left as zero. */
839 1.1 christos /* s_lnnoptr left as zero. */
840 1.1 christos /* s_nreloc left as zero. */
841 1.1 christos /* s_nlnno left as zero. */
842 1.1 christos flags = STYP_DATA;
843 1.1 christos if (align > 13)
844 1.1 christos align = 13;
845 1.1 christos if (u64)
846 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_flags), flags);
847 1.1 christos else
848 1.1 christos set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_flags), flags);
849 1.1 christos
850 1.1 christos return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf,
851 1.1 christos u64 ? SCNHSZ64 : SCNHSZ32,
852 1.1 christos errmsg, err);
853 1.1 christos }
854 1.1 christos
855 1.1 christos /* Write out a complete XCOFF file. */
856 1.1 christos
857 1.1 christos static const char *
858 1.1 christos simple_object_xcoff_write_to_file (simple_object_write *sobj, int descriptor,
859 1.1 christos int *err)
860 1.1 christos {
861 1.1 christos struct simple_object_xcoff_read *ocr =
862 1.1 christos (struct simple_object_xcoff_read *) sobj->data;
863 1.1 christos int u64 = ocr->magic == U64_TOCMAGIC;
864 1.1 christos unsigned int nscns, secnum;
865 1.1 christos simple_object_write_section *section;
866 1.1 christos off_t scnhdr_offset;
867 1.1 christos size_t symtab_offset;
868 1.1 christos off_t secsym_offset;
869 1.1 christos unsigned int nsyms;
870 1.1 christos size_t offset;
871 1.1 christos size_t name_offset;
872 1.1 christos const char *errmsg;
873 1.1 christos unsigned char strsizebuf[4];
874 1.1 christos /* The interface doesn't give us access to the name of the input file
875 1.1 christos yet. We want to use its basename for the FILE symbol. This is
876 1.1 christos what 'gas' uses when told to assemble from stdin. */
877 1.1 christos const char *source_filename = "fake";
878 1.1 christos size_t sflen;
879 1.1 christos union
880 1.1 christos {
881 1.1 christos struct external_syment sym;
882 1.1 christos union external_auxent aux;
883 1.1 christos } syms[2];
884 1.1 christos void (*set_16) (unsigned char *, unsigned short);
885 1.1 christos void (*set_32) (unsigned char *, unsigned int);
886 1.1 christos
887 1.1 christos set_16 = simple_object_set_big_16;
888 1.1 christos set_32 = simple_object_set_big_32;
889 1.1 christos
890 1.1 christos nscns = 0;
891 1.1 christos for (section = sobj->sections; section != NULL; section = section->next)
892 1.1 christos ++nscns;
893 1.1 christos
894 1.1 christos scnhdr_offset = sizeof (struct external_filehdr) - (u64 ? 4 : 0);
895 1.1 christos offset = scnhdr_offset + nscns * (u64 ? SCNHSZ64 : SCNHSZ32);
896 1.1 christos name_offset = 4;
897 1.1 christos for (section = sobj->sections; section != NULL; section = section->next)
898 1.1 christos {
899 1.1 christos size_t mask;
900 1.1 christos size_t new_offset;
901 1.1 christos size_t scnsize;
902 1.1 christos struct simple_object_write_section_buffer *buffer;
903 1.1 christos
904 1.1 christos mask = (1U << section->align) - 1;
905 1.1 christos new_offset = offset & mask;
906 1.1 christos new_offset &= ~ mask;
907 1.1 christos while (new_offset > offset)
908 1.1 christos {
909 1.1 christos unsigned char zeroes[16];
910 1.1 christos size_t write;
911 1.1 christos
912 1.1 christos memset (zeroes, 0, sizeof zeroes);
913 1.1 christos write = new_offset - offset;
914 1.1 christos if (write > sizeof zeroes)
915 1.1 christos write = sizeof zeroes;
916 1.1 christos if (!simple_object_internal_write (descriptor, offset, zeroes, write,
917 1.1 christos &errmsg, err))
918 1.1 christos return errmsg;
919 1.1 christos }
920 1.1 christos
921 1.1 christos scnsize = 0;
922 1.1 christos for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
923 1.1 christos {
924 1.1 christos if (!simple_object_internal_write (descriptor, offset + scnsize,
925 1.1 christos ((const unsigned char *)
926 1.1 christos buffer->buffer),
927 1.1 christos buffer->size, &errmsg, err))
928 1.1 christos return errmsg;
929 1.1 christos scnsize += buffer->size;
930 1.1 christos }
931 1.1 christos
932 1.1 christos if (!simple_object_xcoff_write_scnhdr (sobj, descriptor, section->name,
933 1.1 christos &name_offset, scnhdr_offset,
934 1.1 christos scnsize, offset, section->align,
935 1.1 christos &errmsg, err))
936 1.1 christos return errmsg;
937 1.1 christos
938 1.1 christos scnhdr_offset += u64 ? SCNHSZ64 : SCNHSZ32;
939 1.1 christos offset += scnsize;
940 1.1 christos }
941 1.1 christos
942 1.1 christos /* Symbol table is always half-word aligned. */
943 1.1 christos offset += (offset & 1);
944 1.1 christos /* There is a file symbol and a section symbol per section,
945 1.1 christos and each of these has a single auxiliary symbol following. */
946 1.1 christos nsyms = 2 * (nscns + 1);
947 1.1 christos symtab_offset = offset;
948 1.1 christos /* Advance across space reserved for symbol table to locate
949 1.1 christos start of string table. */
950 1.1 christos offset += nsyms * SYMESZ;
951 1.1 christos
952 1.1 christos /* Write out file symbol. */
953 1.1 christos memset (&syms[0], 0, sizeof (syms));
954 1.1 christos if (!u64)
955 1.1 christos strcpy ((char *)&syms[0].sym.u.xcoff32.n.n_name[0], ".file");
956 1.1 christos set_16 (&syms[0].sym.n_scnum[0], N_DEBUG);
957 1.1 christos set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE);
958 1.1 christos syms[0].sym.n_sclass[0] = C_FILE;
959 1.1 christos syms[0].sym.n_numaux[0] = 1;
960 1.1 christos /* The name need not be nul-terminated if it fits into the x_fname field
961 1.1 christos directly, but must be if it has to be placed into the string table. */
962 1.1 christos sflen = strlen (source_filename);
963 1.1 christos if (sflen <= FILNMLEN)
964 1.1 christos memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
965 1.1 christos else
966 1.1 christos {
967 1.1 christos set_32 (&syms[1].aux.x_file._x.x_offset[0], name_offset);
968 1.1 christos if (!simple_object_internal_write (descriptor, offset + name_offset,
969 1.1 christos ((const unsigned char *)
970 1.1 christos source_filename),
971 1.1 christos sflen + 1, &errmsg, err))
972 1.1 christos return errmsg;
973 1.1 christos name_offset += strlen (source_filename) + 1;
974 1.1 christos }
975 1.1 christos if (!simple_object_internal_write (descriptor, symtab_offset,
976 1.1 christos (const unsigned char *) &syms[0],
977 1.1 christos sizeof (syms), &errmsg, err))
978 1.1 christos return errmsg;
979 1.1 christos
980 1.1 christos /* Write the string table length, followed by the strings and section
981 1.1 christos symbols in step with each other. */
982 1.1 christos set_32 (strsizebuf, name_offset);
983 1.1 christos if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
984 1.1 christos &errmsg, err))
985 1.1 christos return errmsg;
986 1.1 christos
987 1.1 christos name_offset = 4;
988 1.1 christos secsym_offset = symtab_offset + sizeof (syms);
989 1.1 christos memset (&syms[0], 0, sizeof (syms));
990 1.1 christos set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE);
991 1.1 christos syms[0].sym.n_sclass[0] = C_STAT;
992 1.1 christos syms[0].sym.n_numaux[0] = 1;
993 1.1 christos secnum = 1;
994 1.1 christos
995 1.1 christos for (section = sobj->sections; section != NULL; section = section->next)
996 1.1 christos {
997 1.1 christos size_t namelen;
998 1.1 christos size_t scnsize;
999 1.1 christos struct simple_object_write_section_buffer *buffer;
1000 1.1 christos
1001 1.1 christos namelen = strlen (section->name);
1002 1.1 christos set_16 (&syms[0].sym.n_scnum[0], secnum++);
1003 1.1 christos scnsize = 0;
1004 1.1 christos for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
1005 1.1 christos scnsize += buffer->size;
1006 1.1 christos set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
1007 1.1 christos if (namelen > SCNNMLEN)
1008 1.1 christos {
1009 1.1 christos set_32 (&syms[0].sym.u.xcoff32.n.n.n_zeroes[0], 0);
1010 1.1 christos set_32 (&syms[0].sym.u.xcoff32.n.n.n_offset[0], name_offset);
1011 1.1 christos if (!simple_object_internal_write (descriptor, offset + name_offset,
1012 1.1 christos ((const unsigned char *)
1013 1.1 christos section->name),
1014 1.1 christos namelen + 1, &errmsg, err))
1015 1.1 christos return errmsg;
1016 1.1 christos name_offset += namelen + 1;
1017 1.1 christos }
1018 1.1 christos else
1019 1.1 christos {
1020 1.1 christos memcpy (&syms[0].sym.u.xcoff32.n.n_name[0], section->name,
1021 1.1 christos strlen (section->name));
1022 1.1 christos memset (&syms[0].sym.u.xcoff32.n.n_name[strlen (section->name)], 0,
1023 1.1 christos N_SYMNMLEN - strlen (section->name));
1024 1.1 christos }
1025 1.1 christos
1026 1.1 christos if (!simple_object_internal_write (descriptor, secsym_offset,
1027 1.1 christos (const unsigned char *) &syms[0],
1028 1.1 christos sizeof (syms), &errmsg, err))
1029 1.1 christos return errmsg;
1030 1.1 christos secsym_offset += sizeof (syms);
1031 1.1 christos }
1032 1.1 christos
1033 1.1 christos if (!simple_object_xcoff_write_filehdr (sobj, descriptor, nscns,
1034 1.1 christos symtab_offset, nsyms, &errmsg, err))
1035 1.1 christos return errmsg;
1036 1.1 christos
1037 1.1 christos return NULL;
1038 1.1 christos }
1039 1.1 christos
1040 1.1 christos /* Release the private data for an simple_object_write structure. */
1041 1.1 christos
1042 1.1 christos static void
1043 1.1 christos simple_object_xcoff_release_write (void *data)
1044 1.1 christos {
1045 1.1 christos XDELETE (data);
1046 1.1 christos }
1047 1.1 christos
1048 1.1 christos /* The XCOFF functions. */
1049 1.1 christos
1050 1.1 christos const struct simple_object_functions simple_object_xcoff_functions =
1051 1.1 christos {
1052 1.1 christos simple_object_xcoff_match,
1053 1.1 christos simple_object_xcoff_find_sections,
1054 1.1 christos simple_object_xcoff_fetch_attributes,
1055 1.1 christos simple_object_xcoff_release_read,
1056 1.1 christos simple_object_xcoff_attributes_merge,
1057 1.1 christos simple_object_xcoff_release_attributes,
1058 1.1 christos simple_object_xcoff_start_write,
1059 1.1 christos simple_object_xcoff_write_to_file,
1060 1.1.1.2 christos simple_object_xcoff_release_write,
1061 1.1.1.2 christos NULL
1062 1.1 christos };
1063