merge from gcc
[deliverable/binutils-gdb.git] / libiberty / simple-object-coff.c
1 /* simple-object-coff.c -- routines to manipulate COFF object files.
2 Copyright 2010 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
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 /* COFF structures and constants. */
46
47 /* COFF 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 unsigned char f_symptr[4]; /* file pointer to symtab */
55 unsigned char f_nsyms[4]; /* number of symtab entries */
56 unsigned char f_opthdr[2]; /* sizeof(optional hdr) */
57 unsigned char f_flags[2]; /* flags */
58 };
59
60 /* Bits for filehdr f_flags field. */
61
62 #define F_EXEC (0x0002)
63 #define IMAGE_FILE_SYSTEM (0x1000)
64 #define IMAGE_FILE_DLL (0x2000)
65
66 /* COFF section header. */
67
68 struct external_scnhdr
69 {
70 unsigned char s_name[8]; /* section name */
71 unsigned char s_paddr[4]; /* physical address, aliased s_nlib */
72 unsigned char s_vaddr[4]; /* virtual address */
73 unsigned char s_size[4]; /* section size */
74 unsigned char s_scnptr[4]; /* file ptr to raw data for section */
75 unsigned char s_relptr[4]; /* file ptr to relocation */
76 unsigned char s_lnnoptr[4]; /* file ptr to line numbers */
77 unsigned char s_nreloc[2]; /* number of relocation entries */
78 unsigned char s_nlnno[2]; /* number of line number entries */
79 unsigned char s_flags[4]; /* flags */
80 };
81
82 /* The length of the s_name field in struct external_scnhdr. */
83
84 #define SCNNMLEN (8)
85
86 /* Bits for scnhdr s_flags field. This includes some bits defined
87 only for PE. This may need to be moved into coff_magic. */
88
89 #define STYP_DATA (1 << 6)
90 #define IMAGE_SCN_MEM_DISCARDABLE (1 << 25)
91 #define IMAGE_SCN_MEM_SHARED (1 << 28)
92 #define IMAGE_SCN_MEM_READ (1 << 30)
93
94 #define IMAGE_SCN_ALIGN_POWER_BIT_POS 20
95 #define IMAGE_SCN_ALIGN_POWER_CONST(val) \
96 (((val) + 1) << IMAGE_SCN_ALIGN_POWER_BIT_POS)
97
98 /* COFF symbol table entry. */
99
100 #define E_SYMNMLEN 8 /* # characters in a symbol name */
101
102 struct external_syment
103 {
104 union
105 {
106 unsigned char e_name[E_SYMNMLEN];
107
108 struct
109 {
110 unsigned char e_zeroes[4];
111 unsigned char e_offset[4];
112 } e;
113 } e;
114
115 unsigned char e_value[4];
116 unsigned char e_scnum[2];
117 unsigned char e_type[2];
118 unsigned char e_sclass[1];
119 unsigned char e_numaux[1];
120 };
121
122 /* Length allowed for filename in aux sym format 4. */
123
124 #define E_FILNMLEN 18
125
126 /* Omits x_sym and other unused variants. */
127
128 union external_auxent
129 {
130 /* Aux sym format 4: file. */
131 union
132 {
133 char x_fname[E_FILNMLEN];
134 struct
135 {
136 unsigned char x_zeroes[4];
137 unsigned char x_offset[4];
138 } x_n;
139 } x_file;
140 /* Aux sym format 5: section. */
141 struct
142 {
143 unsigned char x_scnlen[4]; /* section length */
144 unsigned char x_nreloc[2]; /* # relocation entries */
145 unsigned char x_nlinno[2]; /* # line numbers */
146 unsigned char x_checksum[4]; /* section COMDAT checksum */
147 unsigned char x_associated[2]; /* COMDAT assoc section index */
148 unsigned char x_comdat[1]; /* COMDAT selection number */
149 } x_scn;
150 };
151
152 /* Symbol-related constants. */
153
154 #define IMAGE_SYM_DEBUG (-2)
155 #define IMAGE_SYM_TYPE_NULL (0)
156 #define IMAGE_SYM_DTYPE_NULL (0)
157 #define IMAGE_SYM_CLASS_STATIC (3)
158 #define IMAGE_SYM_CLASS_FILE (103)
159
160 #define IMAGE_SYM_TYPE \
161 ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
162
163 /* Private data for an simple_object_read. */
164
165 struct simple_object_coff_read
166 {
167 /* Magic number. */
168 unsigned short magic;
169 /* Whether the file is big-endian. */
170 unsigned char is_big_endian;
171 /* Number of sections. */
172 unsigned short nscns;
173 /* File offset of symbol table. */
174 off_t symptr;
175 /* Number of symbol table entries. */
176 unsigned int nsyms;
177 /* Flags. */
178 unsigned short flags;
179 /* Offset of section headers in file. */
180 off_t scnhdr_offset;
181 };
182
183 /* Private data for an simple_object_attributes. */
184
185 struct simple_object_coff_attributes
186 {
187 /* Magic number. */
188 unsigned short magic;
189 /* Whether the file is big-endian. */
190 unsigned char is_big_endian;
191 /* Flags. */
192 unsigned short flags;
193 };
194
195 /* There is no magic number which indicates a COFF file as opposed to
196 any other sort of file. Instead, each COFF file starts with a
197 two-byte magic number which also indicates the type of the target.
198 This struct holds a magic number as well as characteristics of that
199 COFF format. */
200
201 struct coff_magic_struct
202 {
203 /* Magic number. */
204 unsigned short magic;
205 /* Whether this magic number is for a big-endian file. */
206 unsigned char is_big_endian;
207 /* Flag bits, in the f_flags fields, which indicates that this file
208 is not a relocatable object file. There is no flag which
209 specifically indicates a relocatable object file, it is only
210 implied by the absence of these flags. */
211 unsigned short non_object_flags;
212 };
213
214 /* This is a list of the COFF magic numbers which we recognize, namely
215 the ones used on Windows. More can be added as needed. */
216
217 static const struct coff_magic_struct coff_magic[] =
218 {
219 /* i386. */
220 { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL },
221 /* x86_64. */
222 { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }
223 };
224
225 /* See if we have a COFF file. */
226
227 static void *
228 simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
229 int descriptor, off_t offset,
230 const char *segment_name ATTRIBUTE_UNUSED,
231 const char **errmsg, int *err)
232 {
233 size_t c;
234 unsigned short magic_big;
235 unsigned short magic_little;
236 unsigned short magic;
237 size_t i;
238 int is_big_endian;
239 unsigned short (*fetch_16) (const unsigned char *);
240 unsigned int (*fetch_32) (const unsigned char *);
241 unsigned char hdrbuf[sizeof (struct external_filehdr)];
242 unsigned short flags;
243 struct simple_object_coff_read *ocr;
244
245 c = sizeof (coff_magic) / sizeof (coff_magic[0]);
246 magic_big = simple_object_fetch_big_16 (header);
247 magic_little = simple_object_fetch_little_16 (header);
248 for (i = 0; i < c; ++i)
249 {
250 if (coff_magic[i].is_big_endian
251 ? coff_magic[i].magic == magic_big
252 : coff_magic[i].magic == magic_little)
253 break;
254 }
255 if (i >= c)
256 {
257 *errmsg = NULL;
258 *err = 0;
259 return NULL;
260 }
261 is_big_endian = coff_magic[i].is_big_endian;
262
263 magic = is_big_endian ? magic_big : magic_little;
264 fetch_16 = (is_big_endian
265 ? simple_object_fetch_big_16
266 : simple_object_fetch_little_16);
267 fetch_32 = (is_big_endian
268 ? simple_object_fetch_big_32
269 : simple_object_fetch_little_32);
270
271 if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
272 errmsg, err))
273 return NULL;
274
275 flags = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_flags));
276 if ((flags & coff_magic[i].non_object_flags) != 0)
277 {
278 *errmsg = "not relocatable object file";
279 *err = 0;
280 return NULL;
281 }
282
283 ocr = XNEW (struct simple_object_coff_read);
284 ocr->magic = magic;
285 ocr->is_big_endian = is_big_endian;
286 ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
287 ocr->symptr = fetch_32 (hdrbuf
288 + offsetof (struct external_filehdr, f_symptr));
289 ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, f_nsyms));
290 ocr->flags = flags;
291 ocr->scnhdr_offset = (sizeof (struct external_filehdr)
292 + fetch_16 (hdrbuf + offsetof (struct external_filehdr,
293 f_opthdr)));
294
295 return (void *) ocr;
296 }
297
298 /* Read the string table in a COFF file. */
299
300 static char *
301 simple_object_coff_read_strtab (simple_object_read *sobj, size_t *strtab_size,
302 const char **errmsg, int *err)
303 {
304 struct simple_object_coff_read *ocr =
305 (struct simple_object_coff_read *) sobj->data;
306 off_t strtab_offset;
307 unsigned char strsizebuf[4];
308 size_t strsize;
309 char *strtab;
310
311 strtab_offset = sobj->offset + ocr->symptr
312 + ocr->nsyms * sizeof (struct external_syment);
313 if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
314 strsizebuf, 4, errmsg, err))
315 return NULL;
316 strsize = (ocr->is_big_endian
317 ? simple_object_fetch_big_32 (strsizebuf)
318 : simple_object_fetch_little_32 (strsizebuf));
319 strtab = XNEWVEC (char, strsize);
320 if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
321 (unsigned char *) strtab, strsize, errmsg,
322 err))
323 {
324 XDELETEVEC (strtab);
325 return NULL;
326 }
327 *strtab_size = strsize;
328 return strtab;
329 }
330
331 /* Find all sections in a COFF file. */
332
333 static const char *
334 simple_object_coff_find_sections (simple_object_read *sobj,
335 int (*pfn) (void *, const char *,
336 off_t offset, off_t length),
337 void *data,
338 int *err)
339 {
340 struct simple_object_coff_read *ocr =
341 (struct simple_object_coff_read *) sobj->data;
342 size_t scnhdr_size;
343 unsigned char *scnbuf;
344 const char *errmsg;
345 unsigned int (*fetch_32) (const unsigned char *);
346 unsigned int nscns;
347 char *strtab;
348 size_t strtab_size;
349 unsigned int i;
350
351 scnhdr_size = sizeof (struct external_scnhdr);
352 scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns);
353 if (!simple_object_internal_read (sobj->descriptor,
354 sobj->offset + ocr->scnhdr_offset,
355 scnbuf, scnhdr_size * ocr->nscns, &errmsg,
356 err))
357 {
358 XDELETEVEC (scnbuf);
359 return errmsg;
360 }
361
362 fetch_32 = (ocr->is_big_endian
363 ? simple_object_fetch_big_32
364 : simple_object_fetch_little_32);
365
366 nscns = ocr->nscns;
367 strtab = NULL;
368 strtab_size = 0;
369 for (i = 0; i < nscns; ++i)
370 {
371 unsigned char *scnhdr;
372 unsigned char *scnname;
373 char namebuf[SCNNMLEN + 1];
374 char *name;
375 off_t scnptr;
376 unsigned int size;
377
378 scnhdr = scnbuf + i * scnhdr_size;
379 scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
380 memcpy (namebuf, scnname, SCNNMLEN);
381 namebuf[SCNNMLEN] = '\0';
382 name = &namebuf[0];
383 if (namebuf[0] == '/')
384 {
385 size_t strindex;
386 char *end;
387
388 strindex = strtol (namebuf + 1, &end, 10);
389 if (*end == '\0')
390 {
391 /* The real section name is found in the string
392 table. */
393 if (strtab == NULL)
394 {
395 strtab = simple_object_coff_read_strtab (sobj,
396 &strtab_size,
397 &errmsg, err);
398 if (strtab == NULL)
399 {
400 XDELETEVEC (scnbuf);
401 return errmsg;
402 }
403 }
404
405 if (strindex < 4 || strindex >= strtab_size)
406 {
407 XDELETEVEC (strtab);
408 XDELETEVEC (scnbuf);
409 *err = 0;
410 return "section string index out of range";
411 }
412
413 name = strtab + strindex;
414 }
415 }
416
417 scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_scnptr));
418 size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_size));
419
420 if (!(*pfn) (data, name, scnptr, size))
421 break;
422 }
423
424 if (strtab != NULL)
425 XDELETEVEC (strtab);
426 XDELETEVEC (scnbuf);
427
428 return NULL;
429 }
430
431 /* Fetch the attributes for an simple_object_read. */
432
433 static void *
434 simple_object_coff_fetch_attributes (simple_object_read *sobj,
435 const char **errmsg ATTRIBUTE_UNUSED,
436 int *err ATTRIBUTE_UNUSED)
437 {
438 struct simple_object_coff_read *ocr =
439 (struct simple_object_coff_read *) sobj->data;
440 struct simple_object_coff_attributes *ret;
441
442 ret = XNEW (struct simple_object_coff_attributes);
443 ret->magic = ocr->magic;
444 ret->is_big_endian = ocr->is_big_endian;
445 ret->flags = ocr->flags;
446 return ret;
447 }
448
449 /* Release the private data for an simple_object_read. */
450
451 static void
452 simple_object_coff_release_read (void *data)
453 {
454 XDELETE (data);
455 }
456
457 /* Compare two attributes structures. */
458
459 static const char *
460 simple_object_coff_attributes_compare (void *data1, void *data2, int *err)
461 {
462 struct simple_object_coff_attributes *attrs1 =
463 (struct simple_object_coff_attributes *) data1;
464 struct simple_object_coff_attributes *attrs2 =
465 (struct simple_object_coff_attributes *) data2;
466
467 if (attrs1->magic != attrs2->magic
468 || attrs1->is_big_endian != attrs2->is_big_endian)
469 {
470 *err = 0;
471 return "COFF object format mismatch";
472 }
473 return NULL;
474 }
475
476 /* Release the private data for an attributes structure. */
477
478 static void
479 simple_object_coff_release_attributes (void *data)
480 {
481 XDELETE (data);
482 }
483
484 /* Prepare to write out a file. */
485
486 static void *
487 simple_object_coff_start_write (void *attributes_data,
488 const char **errmsg ATTRIBUTE_UNUSED,
489 int *err ATTRIBUTE_UNUSED)
490 {
491 struct simple_object_coff_attributes *attrs =
492 (struct simple_object_coff_attributes *) attributes_data;
493 struct simple_object_coff_attributes *ret;
494
495 /* We're just going to record the attributes, but we need to make a
496 copy because the user may delete them. */
497 ret = XNEW (struct simple_object_coff_attributes);
498 *ret = *attrs;
499 return ret;
500 }
501
502 /* Write out a COFF filehdr. */
503
504 static int
505 simple_object_coff_write_filehdr (simple_object_write *sobj, int descriptor,
506 unsigned int nscns, size_t symtab_offset,
507 unsigned int nsyms, const char **errmsg,
508 int *err)
509 {
510 struct simple_object_coff_attributes *attrs =
511 (struct simple_object_coff_attributes *) sobj->data;
512 unsigned char hdrbuf[sizeof (struct external_filehdr)];
513 unsigned char *hdr;
514 void (*set_16) (unsigned char *, unsigned short);
515 void (*set_32) (unsigned char *, unsigned int);
516
517 hdr = &hdrbuf[0];
518
519 set_16 = (attrs->is_big_endian
520 ? simple_object_set_big_16
521 : simple_object_set_little_16);
522 set_32 = (attrs->is_big_endian
523 ? simple_object_set_big_32
524 : simple_object_set_little_32);
525
526 memset (hdr, 0, sizeof (struct external_filehdr));
527
528 set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
529 set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns);
530 /* f_timdat left as zero. */
531 set_32 (hdr + offsetof (struct external_filehdr, f_symptr), symtab_offset);
532 set_32 (hdr + offsetof (struct external_filehdr, f_nsyms), nsyms);
533 /* f_opthdr left as zero. */
534 set_16 (hdr + offsetof (struct external_filehdr, f_flags), attrs->flags);
535
536 return simple_object_internal_write (descriptor, 0, hdrbuf,
537 sizeof (struct external_filehdr),
538 errmsg, err);
539 }
540
541 /* Write out a COFF section header. */
542
543 static int
544 simple_object_coff_write_scnhdr (simple_object_write *sobj, int descriptor,
545 const char *name, size_t *name_offset,
546 off_t scnhdr_offset, size_t scnsize,
547 off_t offset, unsigned int align,
548 const char **errmsg, int *err)
549 {
550 struct simple_object_coff_attributes *attrs =
551 (struct simple_object_coff_attributes *) sobj->data;
552 void (*set_32) (unsigned char *, unsigned int);
553 unsigned char hdrbuf[sizeof (struct external_scnhdr)];
554 unsigned char *hdr;
555 size_t namelen;
556 unsigned int flags;
557
558 set_32 = (attrs->is_big_endian
559 ? simple_object_set_big_32
560 : simple_object_set_little_32);
561
562 memset (hdrbuf, 0, sizeof hdrbuf);
563 hdr = &hdrbuf[0];
564
565 namelen = strlen (name);
566 if (namelen <= SCNNMLEN)
567 strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), name,
568 SCNNMLEN);
569 else
570 {
571 snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name),
572 SCNNMLEN, "/%lu", (unsigned long) *name_offset);
573 *name_offset += namelen + 1;
574 }
575
576 /* s_paddr left as zero. */
577 /* s_vaddr left as zero. */
578 set_32 (hdr + offsetof (struct external_scnhdr, s_size), scnsize);
579 set_32 (hdr + offsetof (struct external_scnhdr, s_scnptr), offset);
580 /* s_relptr left as zero. */
581 /* s_lnnoptr left as zero. */
582 /* s_nreloc left as zero. */
583 /* s_nlnno left as zero. */
584 flags = (STYP_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED
585 | IMAGE_SCN_MEM_READ);
586 /* PE can represent alignment up to 13. */
587 if (align > 13)
588 align = 13;
589 flags |= IMAGE_SCN_ALIGN_POWER_CONST(align);
590 set_32 (hdr + offsetof (struct external_scnhdr, s_flags), flags);
591
592 return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf,
593 sizeof (struct external_scnhdr),
594 errmsg, err);
595 }
596
597 /* Write out a complete COFF file. */
598
599 static const char *
600 simple_object_coff_write_to_file (simple_object_write *sobj, int descriptor,
601 int *err)
602 {
603 struct simple_object_coff_attributes *attrs =
604 (struct simple_object_coff_attributes *) sobj->data;
605 unsigned int nscns, secnum;
606 simple_object_write_section *section;
607 off_t scnhdr_offset;
608 size_t symtab_offset;
609 off_t secsym_offset;
610 unsigned int nsyms;
611 size_t offset;
612 size_t name_offset;
613 const char *errmsg;
614 unsigned char strsizebuf[4];
615 /* The interface doesn't give us access to the name of the input file
616 yet. We want to use its basename for the FILE symbol. This is
617 what 'gas' uses when told to assemble from stdin. */
618 const char *source_filename = "fake";
619 size_t sflen;
620 union
621 {
622 struct external_syment sym;
623 union external_auxent aux;
624 } syms[2];
625 void (*set_16) (unsigned char *, unsigned short);
626 void (*set_32) (unsigned char *, unsigned int);
627
628 set_16 = (attrs->is_big_endian
629 ? simple_object_set_big_16
630 : simple_object_set_little_16);
631 set_32 = (attrs->is_big_endian
632 ? simple_object_set_big_32
633 : simple_object_set_little_32);
634
635 nscns = 0;
636 for (section = sobj->sections; section != NULL; section = section->next)
637 ++nscns;
638
639 scnhdr_offset = sizeof (struct external_filehdr);
640 offset = scnhdr_offset + nscns * sizeof (struct external_scnhdr);
641 name_offset = 4;
642 for (section = sobj->sections; section != NULL; section = section->next)
643 {
644 size_t mask;
645 size_t new_offset;
646 size_t scnsize;
647 struct simple_object_write_section_buffer *buffer;
648
649 mask = (1U << section->align) - 1;
650 new_offset = offset & mask;
651 new_offset &= ~ mask;
652 while (new_offset > offset)
653 {
654 unsigned char zeroes[16];
655 size_t write;
656
657 memset (zeroes, 0, sizeof zeroes);
658 write = new_offset - offset;
659 if (write > sizeof zeroes)
660 write = sizeof zeroes;
661 if (!simple_object_internal_write (descriptor, offset, zeroes, write,
662 &errmsg, err))
663 return errmsg;
664 }
665
666 scnsize = 0;
667 for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
668 {
669 if (!simple_object_internal_write (descriptor, offset + scnsize,
670 ((const unsigned char *)
671 buffer->buffer),
672 buffer->size, &errmsg, err))
673 return errmsg;
674 scnsize += buffer->size;
675 }
676
677 if (!simple_object_coff_write_scnhdr (sobj, descriptor, section->name,
678 &name_offset, scnhdr_offset,
679 scnsize, offset, section->align,
680 &errmsg, err))
681 return errmsg;
682
683 scnhdr_offset += sizeof (struct external_scnhdr);
684 offset += scnsize;
685 }
686
687 /* Symbol table is always half-word aligned. */
688 offset += (offset & 1);
689 /* There is a file symbol and a section symbol per section,
690 and each of these has a single auxiliary symbol following. */
691 nsyms = 2 * (nscns + 1);
692 symtab_offset = offset;
693 /* Advance across space reserved for symbol table to locate
694 start of string table. */
695 offset += nsyms * sizeof (struct external_syment);
696
697 /* Write out file symbol. */
698 memset (&syms[0], 0, sizeof (syms));
699 strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
700 set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
701 set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
702 syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
703 syms[0].sym.e_numaux[0] = 1;
704 /* The name need not be nul-terminated if it fits into the x_fname field
705 directly, but must be if it has to be placed into the string table. */
706 sflen = strlen (source_filename);
707 if (sflen <= E_FILNMLEN)
708 memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
709 else
710 {
711 set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
712 if (!simple_object_internal_write (descriptor, offset + name_offset,
713 ((const unsigned char *)
714 source_filename),
715 sflen + 1, &errmsg, err))
716 return errmsg;
717 name_offset += strlen (source_filename) + 1;
718 }
719 if (!simple_object_internal_write (descriptor, symtab_offset,
720 (const unsigned char *) &syms[0],
721 sizeof (syms), &errmsg, err))
722 return errmsg;
723
724 /* Write the string table length, followed by the strings and section
725 symbols in step with each other. */
726 set_32 (strsizebuf, name_offset);
727 if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
728 &errmsg, err))
729 return errmsg;
730
731 name_offset = 4;
732 secsym_offset = symtab_offset + sizeof (syms);
733 memset (&syms[0], 0, sizeof (syms));
734 set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
735 syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
736 syms[0].sym.e_numaux[0] = 1;
737 secnum = 1;
738
739 for (section = sobj->sections; section != NULL; section = section->next)
740 {
741 size_t namelen;
742 size_t scnsize;
743 struct simple_object_write_section_buffer *buffer;
744
745 namelen = strlen (section->name);
746 set_16 (&syms[0].sym.e_scnum[0], secnum++);
747 scnsize = 0;
748 for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
749 scnsize += buffer->size;
750 set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
751 if (namelen > SCNNMLEN)
752 {
753 set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
754 set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
755 if (!simple_object_internal_write (descriptor, offset + name_offset,
756 ((const unsigned char *)
757 section->name),
758 namelen + 1, &errmsg, err))
759 return errmsg;
760 name_offset += namelen + 1;
761 }
762 else
763 {
764 memcpy (&syms[0].sym.e.e_name[0], section->name,
765 strlen (section->name));
766 memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
767 E_SYMNMLEN - strlen (section->name));
768 }
769
770 if (!simple_object_internal_write (descriptor, secsym_offset,
771 (const unsigned char *) &syms[0],
772 sizeof (syms), &errmsg, err))
773 return errmsg;
774 secsym_offset += sizeof (syms);
775 }
776
777 if (!simple_object_coff_write_filehdr (sobj, descriptor, nscns,
778 symtab_offset, nsyms, &errmsg, err))
779 return errmsg;
780
781 return NULL;
782 }
783
784 /* Release the private data for an simple_object_write structure. */
785
786 static void
787 simple_object_coff_release_write (void *data)
788 {
789 XDELETE (data);
790 }
791
792 /* The COFF functions. */
793
794 const struct simple_object_functions simple_object_coff_functions =
795 {
796 simple_object_coff_match,
797 simple_object_coff_find_sections,
798 simple_object_coff_fetch_attributes,
799 simple_object_coff_release_read,
800 simple_object_coff_attributes_compare,
801 simple_object_coff_release_attributes,
802 simple_object_coff_start_write,
803 simple_object_coff_write_to_file,
804 simple_object_coff_release_write
805 };
This page took 0.048149 seconds and 5 git commands to generate.