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