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