Révision | 07a8e9f0361a21ecced933a32e98a38e7b04d590 (tree) |
---|---|
l'heure | 2013-01-08 05:28:44 |
Auteur | DJ Delorie <dj@redh...> |
Commiter | DJ Delorie |
merge from gcc
@@ -1,3 +1,17 @@ | ||
1 | +2013-01-04 Ian Lance Taylor <iant@google.com> | |
2 | + | |
3 | + PR other/54800 | |
4 | + * simple-object-mach-o.c (simple_object_mach_o_segment): Don't | |
5 | + bother to zero out a buffer we are about to set anyhow. | |
6 | + | |
7 | +2013-01-01 David Edelsohn <dje.gcc@gmail.com> | |
8 | + | |
9 | + * simple-object-xcoff.c: New file. | |
10 | + * Makefile.in: Add it to build machinery. | |
11 | + * simple-object-common.h (simple_object_xcoff_functions): Declare. | |
12 | + * simple-object.c (format_functions): Add | |
13 | + simple_object_xcoff_functions. | |
14 | + | |
1 | 15 | 2012-11-10 Jason Merrill <jason@redhat.com> |
2 | 16 | |
3 | 17 | * cp-demangle.c (d_unqualified_name): Handle abi tags here. |
@@ -146,7 +146,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \ | ||
146 | 146 | random.c regex.c rename.c rindex.c \ |
147 | 147 | safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \ |
148 | 148 | simple-object.c simple-object-coff.c simple-object-elf.c \ |
149 | - simple-object-mach-o.c \ | |
149 | + simple-object-mach-o.c simple-object-xcoff.c \ | |
150 | 150 | snprintf.c sort.c \ |
151 | 151 | spaces.c splay-tree.c stack-limit.c stpcpy.c stpncpy.c \ |
152 | 152 | strcasecmp.c strchr.c strdup.c strerror.c strncasecmp.c \ |
@@ -183,6 +183,7 @@ REQUIRED_OFILES = \ | ||
183 | 183 | ./safe-ctype.$(objext) \ |
184 | 184 | ./simple-object.$(objext) ./simple-object-coff.$(objext) \ |
185 | 185 | ./simple-object-elf.$(objext) ./simple-object-mach-o.$(objext) \ |
186 | + ./simple-object-xcoff.$(objext) \ | |
186 | 187 | ./sort.$(objext) ./spaces.$(objext) \ |
187 | 188 | ./splay-tree.$(objext) ./stack-limit.$(objext) \ |
188 | 189 | ./strerror.$(objext) ./strsignal.$(objext) \ |
@@ -1009,6 +1010,14 @@ $(CONFIGURED_OFILES): stamp-picdir | ||
1009 | 1010 | else true; fi |
1010 | 1011 | $(COMPILE.c) $(srcdir)/simple-object-mach-o.c $(OUTPUT_OPTION) |
1011 | 1012 | |
1013 | +./simple-object-xcoff.$(objext): $(srcdir)/simple-object-xcoff.c config.h \ | |
1014 | + $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \ | |
1015 | + $(srcdir)/simple-object-common.h $(INCDIR)/simple-object.h | |
1016 | + if [ x"$(PICFLAG)" != x ]; then \ | |
1017 | + $(COMPILE.c) $(PICFLAG) $(srcdir)/simple-object-xcoff.c -o pic/$@; \ | |
1018 | + else true; fi | |
1019 | + $(COMPILE.c) $(srcdir)/simple-object-xcoff.c $(OUTPUT_OPTION) | |
1020 | + | |
1012 | 1021 | ./simple-object.$(objext): $(srcdir)/simple-object.c config.h \ |
1013 | 1022 | $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \ |
1014 | 1023 | $(srcdir)/simple-object-common.h $(INCDIR)/simple-object.h |
@@ -148,6 +148,7 @@ struct simple_object_functions | ||
148 | 148 | extern const struct simple_object_functions simple_object_coff_functions; |
149 | 149 | extern const struct simple_object_functions simple_object_elf_functions; |
150 | 150 | extern const struct simple_object_functions simple_object_mach_o_functions; |
151 | +extern const struct simple_object_functions simple_object_xcoff_functions; | |
151 | 152 | |
152 | 153 | /* Read SIZE bytes from DESCRIPTOR at file offset OFFSET into BUFFER. |
153 | 154 | Return non-zero on success. On failure return 0 and set *ERRMSG |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* simple-object-mach-o.c -- routines to manipulate Mach-O object files. |
2 | - Copyright 2010, 2011 Free Software Foundation, Inc. | |
2 | + Copyright 2010, 2011, 2013 Free Software Foundation, Inc. | |
3 | 3 | Written by Ian Lance Taylor, Google. |
4 | 4 | |
5 | 5 | This program is free software; you can redistribute it and/or modify it |
@@ -701,12 +701,13 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset, | ||
701 | 701 | /* Otherwise, make a name like __segment,__section as per the |
702 | 702 | convention in mach-o asm. */ |
703 | 703 | name = &namebuf[0]; |
704 | - memset (namebuf, 0, MACH_O_NAME_LEN * 2 + 2); | |
705 | 704 | memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN); |
705 | + namebuf[MACH_O_NAME_LEN] = '\0'; | |
706 | 706 | l = strlen (namebuf); |
707 | 707 | namebuf[l] = ','; |
708 | 708 | memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset, |
709 | 709 | MACH_O_NAME_LEN); |
710 | + namebuf[l + 1 + MACH_O_NAME_LEN] = '\0'; | |
710 | 711 | } |
711 | 712 | |
712 | 713 | simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr, |
@@ -0,0 +1,898 @@ | ||
1 | +/* simple-object-coff.c -- routines to manipulate XCOFF object files. | |
2 | + Copyright 2013 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.h> | |
25 | +#include <stddef.h> | |
26 | + | |
27 | +#ifdef HAVE_STDLIB_H | |
28 | +#include <stdlib.h> | |
29 | +#endif | |
30 | + | |
31 | +#ifdef HAVE_STDINT_H | |
32 | +#include <stdint.h> | |
33 | +#endif | |
34 | + | |
35 | +#ifdef HAVE_STRING_H | |
36 | +#include <string.h> | |
37 | +#endif | |
38 | + | |
39 | +#ifdef HAVE_INTTYPES_H | |
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) | |
76 | + | |
77 | +/* The known values of f_magic in an XCOFF file header. */ | |
78 | + | |
79 | +#define U802WRMAGIC 0730 /* Writeable text segments. */ | |
80 | +#define U802ROMAGIC 0735 /* Readonly sharable text segments. */ | |
81 | +#define U802TOCMAGIC 0737 /* Readonly text segments and TOC. */ | |
82 | +#define U803XTOCMAGIC 0757 /* Aix 4.3 64-bit XCOFF. */ | |
83 | +#define U64_TOCMAGIC 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) | |
120 | +#define SCNHSZ64 (68) | |
121 | + | |
122 | +/* The length of the s_name field in struct external_scnhdr. */ | |
123 | + | |
124 | +#define SCNNMLEN (8) | |
125 | + | |
126 | +/* Bits for scnhdr s_flags field. */ | |
127 | + | |
128 | +#define STYP_DATA 0x40 | |
129 | + | |
130 | +/* XCOFF symbol table entry. */ | |
131 | + | |
132 | + | |
133 | +#define N_SYMNMLEN (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]; | |
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) | |
179 | + | |
180 | +/* Length allowed for filename in aux sym format 4. */ | |
181 | + | |
182 | +#define FILNMLEN (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]; | |
192 | + struct | |
193 | + { | |
194 | + unsigned char x_zeroes[4]; | |
195 | + unsigned char x_offset[4]; | |
196 | + unsigned char x_pad[FILNMLEN-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) | |
250 | +#define IMAGE_SYM_TYPE_NULL (0) | |
251 | +#define IMAGE_SYM_DTYPE_NULL (0) | |
252 | +#define IMAGE_SYM_CLASS_STATIC (3) | |
253 | +#define IMAGE_SYM_CLASS_FILE (103) | |
254 | + | |
255 | +#define IMAGE_SYM_TYPE \ | |
256 | + ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL) | |
257 | + | |
258 | +#define C_STAT (3) | |
259 | +#define C_FILE (103) | |
260 | + | |
261 | +/* Private data for an simple_object_read. */ | |
262 | + | |
263 | +struct simple_object_xcoff_read | |
264 | +{ | |
265 | + /* Magic number. */ | |
266 | + unsigned short magic; | |
267 | + /* Number of sections. */ | |
268 | + unsigned short nscns; | |
269 | + /* File offset of symbol table. */ | |
270 | + off_t symptr; | |
271 | + /* Number of symbol table entries. */ | |
272 | + unsigned int nsyms; | |
273 | + /* Flags. */ | |
274 | + unsigned short flags; | |
275 | + /* Offset of section headers in file. */ | |
276 | + off_t scnhdr_offset; | |
277 | +}; | |
278 | + | |
279 | +/* Private data for an simple_object_attributes. */ | |
280 | + | |
281 | +struct simple_object_xcoff_attributes | |
282 | +{ | |
283 | + /* Magic number. */ | |
284 | + unsigned short magic; | |
285 | + /* Flags. */ | |
286 | + unsigned short flags; | |
287 | +}; | |
288 | + | |
289 | +/* See if we have a XCOFF file. */ | |
290 | + | |
291 | +static void * | |
292 | +simple_object_xcoff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN], | |
293 | + int descriptor, off_t offset, | |
294 | + const char *segment_name ATTRIBUTE_UNUSED, | |
295 | + const char **errmsg, int *err) | |
296 | +{ | |
297 | + unsigned short magic; | |
298 | + unsigned short (*fetch_16) (const unsigned char *); | |
299 | + unsigned int (*fetch_32) (const unsigned char *); | |
300 | + ulong_type (*fetch_64) (const unsigned char *); | |
301 | + unsigned char hdrbuf[sizeof (struct external_filehdr)]; | |
302 | + struct simple_object_xcoff_read *ocr; | |
303 | + int u64; | |
304 | + | |
305 | + magic = simple_object_fetch_big_16 (header); | |
306 | + | |
307 | + if (magic != U802TOCMAGIC && magic != U64_TOCMAGIC) | |
308 | + { | |
309 | + *errmsg = NULL; | |
310 | + *err = 0; | |
311 | + return NULL; | |
312 | + } | |
313 | + | |
314 | + fetch_16 = simple_object_fetch_big_16; | |
315 | + fetch_32 = simple_object_fetch_big_32; | |
316 | + fetch_64 = simple_object_fetch_big_64; | |
317 | + | |
318 | + if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf, | |
319 | + errmsg, err)) | |
320 | + return NULL; | |
321 | + | |
322 | + u64 = magic == U64_TOCMAGIC; | |
323 | + | |
324 | + ocr = XNEW (struct simple_object_xcoff_read); | |
325 | + ocr->magic = magic; | |
326 | + ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns)); | |
327 | + if (u64) | |
328 | + { | |
329 | + ocr->symptr = fetch_64 (hdrbuf | |
330 | + + offsetof (struct external_filehdr, | |
331 | + u.xcoff64.f_symptr)); | |
332 | + ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, | |
333 | + u.xcoff64.f_nsyms)); | |
334 | + ocr->scnhdr_offset = (sizeof (struct external_filehdr) | |
335 | + + fetch_16 (hdrbuf + offsetof (struct external_filehdr, | |
336 | + u.xcoff64.f_opthdr))); | |
337 | + | |
338 | + } | |
339 | + else | |
340 | + { | |
341 | + ocr->symptr = fetch_32 (hdrbuf | |
342 | + + offsetof (struct external_filehdr, | |
343 | + u.xcoff32.f_symptr)); | |
344 | + ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, | |
345 | + u.xcoff32.f_nsyms)); | |
346 | + ocr->scnhdr_offset = (sizeof (struct external_filehdr) - 4 | |
347 | + + fetch_16 (hdrbuf + offsetof (struct external_filehdr, | |
348 | + u.xcoff32.f_opthdr))); | |
349 | + | |
350 | + } | |
351 | + | |
352 | + return (void *) ocr; | |
353 | +} | |
354 | + | |
355 | +/* Read the string table in a XCOFF file. */ | |
356 | + | |
357 | +static char * | |
358 | +simple_object_xcoff_read_strtab (simple_object_read *sobj, size_t *strtab_size, | |
359 | + const char **errmsg, int *err) | |
360 | +{ | |
361 | + struct simple_object_xcoff_read *ocr = | |
362 | + (struct simple_object_xcoff_read *) sobj->data; | |
363 | + off_t strtab_offset; | |
364 | + unsigned char strsizebuf[4]; | |
365 | + size_t strsize; | |
366 | + char *strtab; | |
367 | + | |
368 | + strtab_offset = sobj->offset + ocr->symptr | |
369 | + + ocr->nsyms * SYMESZ; | |
370 | + if (!simple_object_internal_read (sobj->descriptor, strtab_offset, | |
371 | + strsizebuf, 4, errmsg, err)) | |
372 | + return NULL; | |
373 | + strsize = simple_object_fetch_big_32 (strsizebuf); | |
374 | + strtab = XNEWVEC (char, strsize); | |
375 | + if (!simple_object_internal_read (sobj->descriptor, strtab_offset, | |
376 | + (unsigned char *) strtab, strsize, errmsg, | |
377 | + err)) | |
378 | + { | |
379 | + XDELETEVEC (strtab); | |
380 | + return NULL; | |
381 | + } | |
382 | + *strtab_size = strsize; | |
383 | + return strtab; | |
384 | +} | |
385 | + | |
386 | +/* Find all sections in a XCOFF file. */ | |
387 | + | |
388 | +static const char * | |
389 | +simple_object_xcoff_find_sections (simple_object_read *sobj, | |
390 | + int (*pfn) (void *, const char *, | |
391 | + off_t offset, off_t length), | |
392 | + void *data, | |
393 | + int *err) | |
394 | +{ | |
395 | + struct simple_object_xcoff_read *ocr = | |
396 | + (struct simple_object_xcoff_read *) sobj->data; | |
397 | + int u64 = ocr->magic == U64_TOCMAGIC; | |
398 | + size_t scnhdr_size; | |
399 | + unsigned char *scnbuf; | |
400 | + const char *errmsg; | |
401 | + unsigned int (*fetch_32) (const unsigned char *); | |
402 | + ulong_type (*fetch_64) (const unsigned char *); | |
403 | + unsigned int nscns; | |
404 | + char *strtab; | |
405 | + size_t strtab_size; | |
406 | + unsigned int i; | |
407 | + | |
408 | + scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32; | |
409 | + scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns); | |
410 | + if (!simple_object_internal_read (sobj->descriptor, | |
411 | + sobj->offset + ocr->scnhdr_offset, | |
412 | + scnbuf, scnhdr_size * ocr->nscns, &errmsg, | |
413 | + err)) | |
414 | + { | |
415 | + XDELETEVEC (scnbuf); | |
416 | + return errmsg; | |
417 | + } | |
418 | + | |
419 | + fetch_32 = simple_object_fetch_big_32; | |
420 | + fetch_64 = simple_object_fetch_big_64; | |
421 | + | |
422 | + nscns = ocr->nscns; | |
423 | + strtab = NULL; | |
424 | + strtab_size = 0; | |
425 | + for (i = 0; i < nscns; ++i) | |
426 | + { | |
427 | + unsigned char *scnhdr; | |
428 | + unsigned char *scnname; | |
429 | + char namebuf[SCNNMLEN + 1]; | |
430 | + char *name; | |
431 | + off_t scnptr; | |
432 | + unsigned int size; | |
433 | + | |
434 | + scnhdr = scnbuf + i * scnhdr_size; | |
435 | + scnname = scnhdr + offsetof (struct external_scnhdr, s_name); | |
436 | + memcpy (namebuf, scnname, SCNNMLEN); | |
437 | + namebuf[SCNNMLEN] = '\0'; | |
438 | + name = &namebuf[0]; | |
439 | + if (namebuf[0] == '/') | |
440 | + { | |
441 | + size_t strindex; | |
442 | + char *end; | |
443 | + | |
444 | + strindex = strtol (namebuf + 1, &end, 10); | |
445 | + if (*end == '\0') | |
446 | + { | |
447 | + /* The real section name is found in the string | |
448 | + table. */ | |
449 | + if (strtab == NULL) | |
450 | + { | |
451 | + strtab = simple_object_xcoff_read_strtab (sobj, | |
452 | + &strtab_size, | |
453 | + &errmsg, err); | |
454 | + if (strtab == NULL) | |
455 | + { | |
456 | + XDELETEVEC (scnbuf); | |
457 | + return errmsg; | |
458 | + } | |
459 | + } | |
460 | + | |
461 | + if (strindex < 4 || strindex >= strtab_size) | |
462 | + { | |
463 | + XDELETEVEC (strtab); | |
464 | + XDELETEVEC (scnbuf); | |
465 | + *err = 0; | |
466 | + return "section string index out of range"; | |
467 | + } | |
468 | + | |
469 | + name = strtab + strindex; | |
470 | + } | |
471 | + } | |
472 | + | |
473 | + if (u64) | |
474 | + { | |
475 | + scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr, | |
476 | + u.xcoff64.s_scnptr)); | |
477 | + size = fetch_64 (scnhdr + offsetof (struct external_scnhdr, | |
478 | + u.xcoff64.s_size)); | |
479 | + } | |
480 | + else | |
481 | + { | |
482 | + scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, | |
483 | + u.xcoff32.s_scnptr)); | |
484 | + size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, | |
485 | + u.xcoff32.s_size)); | |
486 | + } | |
487 | + | |
488 | + if (!(*pfn) (data, name, scnptr, size)) | |
489 | + break; | |
490 | + } | |
491 | + | |
492 | + if (strtab != NULL) | |
493 | + XDELETEVEC (strtab); | |
494 | + XDELETEVEC (scnbuf); | |
495 | + | |
496 | + return NULL; | |
497 | +} | |
498 | + | |
499 | +/* Fetch the attributes for an simple_object_read. */ | |
500 | + | |
501 | +static void * | |
502 | +simple_object_xcoff_fetch_attributes (simple_object_read *sobj, | |
503 | + const char **errmsg ATTRIBUTE_UNUSED, | |
504 | + int *err ATTRIBUTE_UNUSED) | |
505 | +{ | |
506 | + struct simple_object_xcoff_read *ocr = | |
507 | + (struct simple_object_xcoff_read *) sobj->data; | |
508 | + struct simple_object_xcoff_attributes *ret; | |
509 | + | |
510 | + ret = XNEW (struct simple_object_xcoff_attributes); | |
511 | + ret->magic = ocr->magic; | |
512 | + ret->flags = ocr->flags; | |
513 | + return ret; | |
514 | +} | |
515 | + | |
516 | +/* Release the private data for an simple_object_read. */ | |
517 | + | |
518 | +static void | |
519 | +simple_object_xcoff_release_read (void *data) | |
520 | +{ | |
521 | + XDELETE (data); | |
522 | +} | |
523 | + | |
524 | +/* Compare two attributes structures. */ | |
525 | + | |
526 | +static const char * | |
527 | +simple_object_xcoff_attributes_merge (void *todata, void *fromdata, int *err) | |
528 | +{ | |
529 | + struct simple_object_xcoff_attributes *to = | |
530 | + (struct simple_object_xcoff_attributes *) todata; | |
531 | + struct simple_object_xcoff_attributes *from = | |
532 | + (struct simple_object_xcoff_attributes *) fromdata; | |
533 | + | |
534 | + if (to->magic != from->magic) | |
535 | + { | |
536 | + *err = 0; | |
537 | + return "XCOFF object format mismatch"; | |
538 | + } | |
539 | + return NULL; | |
540 | +} | |
541 | + | |
542 | +/* Release the private data for an attributes structure. */ | |
543 | + | |
544 | +static void | |
545 | +simple_object_xcoff_release_attributes (void *data) | |
546 | +{ | |
547 | + XDELETE (data); | |
548 | +} | |
549 | + | |
550 | +/* Prepare to write out a file. */ | |
551 | + | |
552 | +static void * | |
553 | +simple_object_xcoff_start_write (void *attributes_data, | |
554 | + const char **errmsg ATTRIBUTE_UNUSED, | |
555 | + int *err ATTRIBUTE_UNUSED) | |
556 | +{ | |
557 | + struct simple_object_xcoff_attributes *attrs = | |
558 | + (struct simple_object_xcoff_attributes *) attributes_data; | |
559 | + struct simple_object_xcoff_attributes *ret; | |
560 | + | |
561 | + /* We're just going to record the attributes, but we need to make a | |
562 | + copy because the user may delete them. */ | |
563 | + ret = XNEW (struct simple_object_xcoff_attributes); | |
564 | + *ret = *attrs; | |
565 | + return ret; | |
566 | +} | |
567 | + | |
568 | +/* Write out a XCOFF filehdr. */ | |
569 | + | |
570 | +static int | |
571 | +simple_object_xcoff_write_filehdr (simple_object_write *sobj, int descriptor, | |
572 | + unsigned int nscns, size_t symtab_offset, | |
573 | + unsigned int nsyms, const char **errmsg, | |
574 | + int *err) | |
575 | +{ | |
576 | + struct simple_object_xcoff_attributes *attrs = | |
577 | + (struct simple_object_xcoff_attributes *) sobj->data; | |
578 | + int u64 = attrs->magic == U64_TOCMAGIC; | |
579 | + unsigned char hdrbuf[sizeof (struct external_filehdr)]; | |
580 | + unsigned char *hdr; | |
581 | + void (*set_16) (unsigned char *, unsigned short); | |
582 | + void (*set_32) (unsigned char *, unsigned int); | |
583 | + void (*set_64) (unsigned char *, ulong_type); | |
584 | + | |
585 | + hdr = &hdrbuf[0]; | |
586 | + | |
587 | + set_16 = simple_object_set_big_16; | |
588 | + set_32 = simple_object_set_big_32; | |
589 | + set_64 = simple_object_set_big_64; | |
590 | + | |
591 | + memset (hdr, 0, sizeof (struct external_filehdr)); | |
592 | + | |
593 | + set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic); | |
594 | + set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns); | |
595 | + /* f_timdat left as zero. */ | |
596 | + if (u64) | |
597 | + { | |
598 | + set_64 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr), | |
599 | + symtab_offset); | |
600 | + set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms), | |
601 | + nsyms); | |
602 | + /* f_opthdr left as zero. */ | |
603 | + set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags), | |
604 | + attrs->flags); | |
605 | + } | |
606 | + else | |
607 | + { | |
608 | + set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_symptr), | |
609 | + symtab_offset); | |
610 | + set_32 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_nsyms), | |
611 | + nsyms); | |
612 | + /* f_opthdr left as zero. */ | |
613 | + set_16 (hdr + offsetof (struct external_filehdr, u.xcoff64.f_flags), | |
614 | + attrs->flags); | |
615 | + } | |
616 | + | |
617 | + return simple_object_internal_write (descriptor, 0, hdrbuf, | |
618 | + sizeof (struct external_filehdr), | |
619 | + errmsg, err); | |
620 | +} | |
621 | + | |
622 | +/* Write out a XCOFF section header. */ | |
623 | + | |
624 | +static int | |
625 | +simple_object_xcoff_write_scnhdr (simple_object_write *sobj, | |
626 | + int descriptor, | |
627 | + const char *name, size_t *name_offset, | |
628 | + off_t scnhdr_offset, size_t scnsize, | |
629 | + off_t offset, unsigned int align, | |
630 | + const char **errmsg, int *err) | |
631 | +{ | |
632 | + struct simple_object_xcoff_read *ocr = | |
633 | + (struct simple_object_xcoff_read *) sobj->data; | |
634 | + int u64 = ocr->magic == U64_TOCMAGIC; | |
635 | + void (*set_32) (unsigned char *, unsigned int); | |
636 | + void (*set_64) (unsigned char *, unsigned int); | |
637 | + unsigned char hdrbuf[sizeof (struct external_scnhdr)]; | |
638 | + unsigned char *hdr; | |
639 | + size_t namelen; | |
640 | + unsigned int flags; | |
641 | + | |
642 | + set_32 = simple_object_set_big_32; | |
643 | + set_64 = simple_object_set_big_32; | |
644 | + | |
645 | + memset (hdrbuf, 0, sizeof hdrbuf); | |
646 | + hdr = &hdrbuf[0]; | |
647 | + | |
648 | + namelen = strlen (name); | |
649 | + if (namelen <= SCNNMLEN) | |
650 | + strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), | |
651 | + name, SCNNMLEN); | |
652 | + else | |
653 | + { | |
654 | + snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name), | |
655 | + SCNNMLEN, "/%lu", (unsigned long) *name_offset); | |
656 | + *name_offset += namelen + 1; | |
657 | + } | |
658 | + | |
659 | + /* s_paddr left as zero. */ | |
660 | + /* s_vaddr left as zero. */ | |
661 | + if (u64) | |
662 | + { | |
663 | + set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_size), | |
664 | + scnsize); | |
665 | + set_64 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_scnptr), | |
666 | + offset); | |
667 | + } | |
668 | + else | |
669 | + { | |
670 | + set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_size), | |
671 | + scnsize); | |
672 | + set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_scnptr), | |
673 | + offset); | |
674 | + } | |
675 | + /* s_relptr left as zero. */ | |
676 | + /* s_lnnoptr left as zero. */ | |
677 | + /* s_nreloc left as zero. */ | |
678 | + /* s_nlnno left as zero. */ | |
679 | + flags = STYP_DATA; | |
680 | + if (align > 13) | |
681 | + align = 13; | |
682 | + if (u64) | |
683 | + set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff64.s_flags), flags); | |
684 | + else | |
685 | + set_32 (hdr + offsetof (struct external_scnhdr, u.xcoff32.s_flags), flags); | |
686 | + | |
687 | + return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf, | |
688 | + u64 ? SCNHSZ64 : SCNHSZ32, | |
689 | + errmsg, err); | |
690 | +} | |
691 | + | |
692 | +/* Write out a complete XCOFF file. */ | |
693 | + | |
694 | +static const char * | |
695 | +simple_object_xcoff_write_to_file (simple_object_write *sobj, int descriptor, | |
696 | + int *err) | |
697 | +{ | |
698 | + struct simple_object_xcoff_read *ocr = | |
699 | + (struct simple_object_xcoff_read *) sobj->data; | |
700 | + int u64 = ocr->magic == U64_TOCMAGIC; | |
701 | + unsigned int nscns, secnum; | |
702 | + simple_object_write_section *section; | |
703 | + off_t scnhdr_offset; | |
704 | + size_t symtab_offset; | |
705 | + off_t secsym_offset; | |
706 | + unsigned int nsyms; | |
707 | + size_t offset; | |
708 | + size_t name_offset; | |
709 | + const char *errmsg; | |
710 | + unsigned char strsizebuf[4]; | |
711 | + /* The interface doesn't give us access to the name of the input file | |
712 | + yet. We want to use its basename for the FILE symbol. This is | |
713 | + what 'gas' uses when told to assemble from stdin. */ | |
714 | + const char *source_filename = "fake"; | |
715 | + size_t sflen; | |
716 | + union | |
717 | + { | |
718 | + struct external_syment sym; | |
719 | + union external_auxent aux; | |
720 | + } syms[2]; | |
721 | + void (*set_16) (unsigned char *, unsigned short); | |
722 | + void (*set_32) (unsigned char *, unsigned int); | |
723 | + | |
724 | + set_16 = simple_object_set_big_16; | |
725 | + set_32 = simple_object_set_big_32; | |
726 | + | |
727 | + nscns = 0; | |
728 | + for (section = sobj->sections; section != NULL; section = section->next) | |
729 | + ++nscns; | |
730 | + | |
731 | + scnhdr_offset = sizeof (struct external_filehdr) - (u64 ? 4 : 0); | |
732 | + offset = scnhdr_offset + nscns * (u64 ? SCNHSZ64 : SCNHSZ32); | |
733 | + name_offset = 4; | |
734 | + for (section = sobj->sections; section != NULL; section = section->next) | |
735 | + { | |
736 | + size_t mask; | |
737 | + size_t new_offset; | |
738 | + size_t scnsize; | |
739 | + struct simple_object_write_section_buffer *buffer; | |
740 | + | |
741 | + mask = (1U << section->align) - 1; | |
742 | + new_offset = offset & mask; | |
743 | + new_offset &= ~ mask; | |
744 | + while (new_offset > offset) | |
745 | + { | |
746 | + unsigned char zeroes[16]; | |
747 | + size_t write; | |
748 | + | |
749 | + memset (zeroes, 0, sizeof zeroes); | |
750 | + write = new_offset - offset; | |
751 | + if (write > sizeof zeroes) | |
752 | + write = sizeof zeroes; | |
753 | + if (!simple_object_internal_write (descriptor, offset, zeroes, write, | |
754 | + &errmsg, err)) | |
755 | + return errmsg; | |
756 | + } | |
757 | + | |
758 | + scnsize = 0; | |
759 | + for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) | |
760 | + { | |
761 | + if (!simple_object_internal_write (descriptor, offset + scnsize, | |
762 | + ((const unsigned char *) | |
763 | + buffer->buffer), | |
764 | + buffer->size, &errmsg, err)) | |
765 | + return errmsg; | |
766 | + scnsize += buffer->size; | |
767 | + } | |
768 | + | |
769 | + if (!simple_object_xcoff_write_scnhdr (sobj, descriptor, section->name, | |
770 | + &name_offset, scnhdr_offset, | |
771 | + scnsize, offset, section->align, | |
772 | + &errmsg, err)) | |
773 | + return errmsg; | |
774 | + | |
775 | + scnhdr_offset += u64 ? SCNHSZ64 : SCNHSZ32; | |
776 | + offset += scnsize; | |
777 | + } | |
778 | + | |
779 | + /* Symbol table is always half-word aligned. */ | |
780 | + offset += (offset & 1); | |
781 | + /* There is a file symbol and a section symbol per section, | |
782 | + and each of these has a single auxiliary symbol following. */ | |
783 | + nsyms = 2 * (nscns + 1); | |
784 | + symtab_offset = offset; | |
785 | + /* Advance across space reserved for symbol table to locate | |
786 | + start of string table. */ | |
787 | + offset += nsyms * SYMESZ; | |
788 | + | |
789 | + /* Write out file symbol. */ | |
790 | + memset (&syms[0], 0, sizeof (syms)); | |
791 | + if (!u64) | |
792 | + strcpy ((char *)&syms[0].sym.u.xcoff32.n.n_name[0], ".file"); | |
793 | + set_16 (&syms[0].sym.n_scnum[0], N_DEBUG); | |
794 | + set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE); | |
795 | + syms[0].sym.n_sclass[0] = C_FILE; | |
796 | + syms[0].sym.n_numaux[0] = 1; | |
797 | + /* The name need not be nul-terminated if it fits into the x_fname field | |
798 | + directly, but must be if it has to be placed into the string table. */ | |
799 | + sflen = strlen (source_filename); | |
800 | + if (sflen <= FILNMLEN) | |
801 | + memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen); | |
802 | + else | |
803 | + { | |
804 | + set_32 (&syms[1].aux.x_file._x.x_offset[0], name_offset); | |
805 | + if (!simple_object_internal_write (descriptor, offset + name_offset, | |
806 | + ((const unsigned char *) | |
807 | + source_filename), | |
808 | + sflen + 1, &errmsg, err)) | |
809 | + return errmsg; | |
810 | + name_offset += strlen (source_filename) + 1; | |
811 | + } | |
812 | + if (!simple_object_internal_write (descriptor, symtab_offset, | |
813 | + (const unsigned char *) &syms[0], | |
814 | + sizeof (syms), &errmsg, err)) | |
815 | + return errmsg; | |
816 | + | |
817 | + /* Write the string table length, followed by the strings and section | |
818 | + symbols in step with each other. */ | |
819 | + set_32 (strsizebuf, name_offset); | |
820 | + if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4, | |
821 | + &errmsg, err)) | |
822 | + return errmsg; | |
823 | + | |
824 | + name_offset = 4; | |
825 | + secsym_offset = symtab_offset + sizeof (syms); | |
826 | + memset (&syms[0], 0, sizeof (syms)); | |
827 | + set_16 (&syms[0].sym.n_type[0], IMAGE_SYM_TYPE); | |
828 | + syms[0].sym.n_sclass[0] = C_STAT; | |
829 | + syms[0].sym.n_numaux[0] = 1; | |
830 | + secnum = 1; | |
831 | + | |
832 | + for (section = sobj->sections; section != NULL; section = section->next) | |
833 | + { | |
834 | + size_t namelen; | |
835 | + size_t scnsize; | |
836 | + struct simple_object_write_section_buffer *buffer; | |
837 | + | |
838 | + namelen = strlen (section->name); | |
839 | + set_16 (&syms[0].sym.n_scnum[0], secnum++); | |
840 | + scnsize = 0; | |
841 | + for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) | |
842 | + scnsize += buffer->size; | |
843 | + set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize); | |
844 | + if (namelen > SCNNMLEN) | |
845 | + { | |
846 | + set_32 (&syms[0].sym.u.xcoff32.n.n.n_zeroes[0], 0); | |
847 | + set_32 (&syms[0].sym.u.xcoff32.n.n.n_offset[0], name_offset); | |
848 | + if (!simple_object_internal_write (descriptor, offset + name_offset, | |
849 | + ((const unsigned char *) | |
850 | + section->name), | |
851 | + namelen + 1, &errmsg, err)) | |
852 | + return errmsg; | |
853 | + name_offset += namelen + 1; | |
854 | + } | |
855 | + else | |
856 | + { | |
857 | + memcpy (&syms[0].sym.u.xcoff32.n.n_name[0], section->name, | |
858 | + strlen (section->name)); | |
859 | + memset (&syms[0].sym.u.xcoff32.n.n_name[strlen (section->name)], 0, | |
860 | + N_SYMNMLEN - strlen (section->name)); | |
861 | + } | |
862 | + | |
863 | + if (!simple_object_internal_write (descriptor, secsym_offset, | |
864 | + (const unsigned char *) &syms[0], | |
865 | + sizeof (syms), &errmsg, err)) | |
866 | + return errmsg; | |
867 | + secsym_offset += sizeof (syms); | |
868 | + } | |
869 | + | |
870 | + if (!simple_object_xcoff_write_filehdr (sobj, descriptor, nscns, | |
871 | + symtab_offset, nsyms, &errmsg, err)) | |
872 | + return errmsg; | |
873 | + | |
874 | + return NULL; | |
875 | +} | |
876 | + | |
877 | +/* Release the private data for an simple_object_write structure. */ | |
878 | + | |
879 | +static void | |
880 | +simple_object_xcoff_release_write (void *data) | |
881 | +{ | |
882 | + XDELETE (data); | |
883 | +} | |
884 | + | |
885 | +/* The XCOFF functions. */ | |
886 | + | |
887 | +const struct simple_object_functions simple_object_xcoff_functions = | |
888 | +{ | |
889 | + simple_object_xcoff_match, | |
890 | + simple_object_xcoff_find_sections, | |
891 | + simple_object_xcoff_fetch_attributes, | |
892 | + simple_object_xcoff_release_read, | |
893 | + simple_object_xcoff_attributes_merge, | |
894 | + simple_object_xcoff_release_attributes, | |
895 | + simple_object_xcoff_start_write, | |
896 | + simple_object_xcoff_write_to_file, | |
897 | + simple_object_xcoff_release_write | |
898 | +}; |
@@ -51,7 +51,8 @@ static const struct simple_object_functions * const format_functions[] = | ||
51 | 51 | { |
52 | 52 | &simple_object_elf_functions, |
53 | 53 | &simple_object_mach_o_functions, |
54 | - &simple_object_coff_functions | |
54 | + &simple_object_coff_functions, | |
55 | + &simple_object_xcoff_functions | |
55 | 56 | }; |
56 | 57 | |
57 | 58 | /* Read data from a file using the simple_object error reporting |