OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [lto/] [lto-coff.c] - Blame information for rev 288

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 288 jeremybenn
/* LTO routines for COFF object files.
2
   Copyright 2009, 2010 Free Software Foundation, Inc.
3
   Contributed by Dave Korn.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING3.  If not see
19
<http://www.gnu.org/licenses/>.  */
20
 
21
#include "config.h"
22
#include "system.h"
23
#include "coretypes.h"
24
#include "toplev.h"
25
#include "lto.h"
26
#include "tm.h"
27
#include "libiberty.h"
28
#include "ggc.h"
29
#include "lto-streamer.h"
30
#include "lto/lto-coff.h"
31
 
32
 
33
/* Rather than implementing a libcoff to match libelf, or attempting to
34
   integrate libbfd into GCC, this file is a self-contained (and very
35
   minimal) COFF format object file reader/writer.  The generated files
36
   will contain a COFF header, a number of COFF section headers, the
37
   section data itself, and a trailing string table for section names.  */
38
 
39
/* Handle opening elf files on hosts, such as Windows, that may use
40
   text file handling that will break binary access.  */
41
 
42
#ifndef O_BINARY
43
#define O_BINARY 0
44
#endif
45
 
46
/* Known header magics for validation, as an array.  */
47
 
48
static const unsigned int coff_machine_array[] = COFF_KNOWN_MACHINES;
49
 
50
/* Number of valid entries (no sentinel) in array.  */
51
 
52
#define NUM_COFF_KNOWN_MACHINES \
53
        (sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
54
 
55
/* Cached object file header.  */
56
 
57
static Coff_header cached_coff_hdr;
58
 
59
/* Flag to indicate if we have read and cached any header yet.  */
60
 
61
static bool cached_coff_hdr_valid = false;
62
 
63
/* The current output file.  */
64
 
65
static lto_file *current_out_file;
66
 
67
 
68
/* Sets the current output file to FILE.  Returns the old output file or
69
   NULL.  */
70
 
71
lto_file *
72
lto_set_current_out_file (lto_file *file)
73
{
74
  lto_file *old_file = current_out_file;
75
  current_out_file = file;
76
  return old_file;
77
}
78
 
79
 
80
/* Returns the current output file.  */
81
 
82
lto_file *
83
lto_get_current_out_file (void)
84
{
85
  return current_out_file;
86
}
87
 
88
 
89
/* COFF section structure constructor.  */
90
 
91
static lto_coff_section *
92
coff_newsection (lto_coff_file *file, const char *name, size_t type)
93
{
94
  lto_coff_section *ptr, **chain_ptr_ptr;
95
 
96
  ptr = XCNEW (lto_coff_section);
97
  ptr->name = name;
98
  ptr->type = type;
99
 
100
  chain_ptr_ptr = &file->section_chain;
101
  while (*chain_ptr_ptr)
102
    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
103
  *chain_ptr_ptr = ptr;
104
 
105
  return ptr;
106
}
107
 
108
 
109
/* COFF section data block structure constructor.  */
110
 
111
static lto_coff_data *
112
coff_newdata (lto_coff_section *sec)
113
{
114
  lto_coff_data *ptr, **chain_ptr_ptr;
115
 
116
  ptr = XCNEW (lto_coff_data);
117
 
118
  chain_ptr_ptr = &sec->data_chain;
119
  while (*chain_ptr_ptr)
120
    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
121
  *chain_ptr_ptr = ptr;
122
 
123
  return ptr;
124
}
125
 
126
 
127
/* Initialize FILE, an LTO file object for FILENAME.  */
128
 
129
static void
130
lto_file_init (lto_file *file, const char *filename, off_t offset)
131
{
132
  file->filename = filename;
133
  file->offset = offset;
134
}
135
 
136
/* Return an error string after an error, or a predetermined one
137
   if ERRCODE is not -1.  */
138
 
139
static const char *
140
coff_errmsg (int errcode)
141
{
142
  return strerror (errcode == -1 ? errno : errcode);
143
}
144
 
145
/* Returns a hash code for P.  */
146
 
147
static hashval_t
148
hash_name (const void *p)
149
{
150
  const struct lto_section_slot *ds = (const struct lto_section_slot *) p;
151
  return (hashval_t) htab_hash_string (ds->name);
152
}
153
 
154
/* Returns nonzero if P1 and P2 are equal.  */
155
 
156
static int
157
eq_name (const void *p1, const void *p2)
158
{
159
  const struct lto_section_slot *s1 =
160
    (const struct lto_section_slot *) p1;
161
  const struct lto_section_slot *s2 =
162
    (const struct lto_section_slot *) p2;
163
 
164
  return strcmp (s1->name, s2->name) == 0;
165
}
166
 
167
 
168
/* Build a hash table whose key is the section names and whose data is
169
   the start and size of each section in the .o file.  */
170
 
171
htab_t
172
lto_obj_build_section_table (lto_file *lto_file)
173
{
174
  lto_coff_file *coff_file = (lto_coff_file *)lto_file;
175
  lto_coff_section *sec;
176
  htab_t section_hash_table;
177
  ssize_t strtab_size;
178
  char *strtab;
179
 
180
  section_hash_table = htab_create (37, hash_name, eq_name, free);
181
 
182
  /* Seek to start of string table.  */
183
  if (coff_file->strtab_offs != lseek (coff_file->fd,
184
                coff_file->base.offset + coff_file->strtab_offs, SEEK_SET))
185
    {
186
      error ("altered or invalid COFF object file");
187
      return section_hash_table;
188
    }
189
 
190
  strtab_size = coff_file->file_size - coff_file->strtab_offs;
191
  strtab = XNEWVEC (char, strtab_size);
192
  if (read (coff_file->fd, strtab, strtab_size) != strtab_size)
193
    {
194
      error ("invalid COFF object file string table");
195
      return section_hash_table;
196
    }
197
 
198
  /* Scan sections looking at names.  */
199
  COFF_FOR_ALL_SECTIONS(coff_file, sec)
200
    {
201
      struct lto_section_slot s_slot;
202
      void **slot;
203
      char *new_name;
204
      int stringoffset;
205
      char *name = (char *) &sec->coffsec.Name[0];
206
 
207
      /* Skip dummy string section if by any chance we see it.  */
208
      if (sec->type == 1)
209
        continue;
210
 
211
      if (name[0] == '/')
212
        {
213
          if (1 != sscanf (&name[1], "%d", &stringoffset)
214
                || stringoffset < 0 || stringoffset >= strtab_size)
215
            {
216
              error ("invalid COFF section name string");
217
              continue;
218
            }
219
          name = strtab + stringoffset;
220
        }
221
      else
222
        {
223
          /* If we cared about the VirtualSize field, we couldn't
224
             crudely trash it like this to guarantee nul-termination
225
             of the Name field.  But we don't, so we do.  */
226
          name[8] = 0;
227
        }
228
      if (strncmp (name, LTO_SECTION_NAME_PREFIX,
229
                        strlen (LTO_SECTION_NAME_PREFIX)) != 0)
230
          continue;
231
 
232
      new_name = XNEWVEC (char, strlen (name) + 1);
233
      strcpy (new_name, name);
234
      s_slot.name = new_name;
235
      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
236
      if (*slot == NULL)
237
        {
238
          struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
239
 
240
          new_slot->name = new_name;
241
          /* The offset into the file for this section.  */
242
          new_slot->start = coff_file->base.offset
243
                        + COFF_GET(&sec->coffsec,PointerToRawData);
244
          new_slot->len = COFF_GET(&sec->coffsec,SizeOfRawData);
245
          *slot = new_slot;
246
        }
247
      else
248
        {
249
          error ("two or more sections for %s:", new_name);
250
          return NULL;
251
        }
252
    }
253
 
254
  free (strtab);
255
  return section_hash_table;
256
}
257
 
258
 
259
/* Begin a new COFF section named NAME with type TYPE in the current output
260
   file.  TYPE is an SHT_* macro from the libelf headers.  */
261
 
262
static void
263
lto_coff_begin_section_with_type (const char *name, size_t type)
264
{
265
  lto_coff_file *file;
266
  size_t sh_name;
267
 
268
  /* Grab the current output file and do some basic assertion checking.  */
269
  file = (lto_coff_file *) lto_get_current_out_file (),
270
  gcc_assert (file);
271
  gcc_assert (!file->scn);
272
 
273
  /* Create a new section.  */
274
  file->scn = coff_newsection (file, name, type);
275
  if (!file->scn)
276
    fatal_error ("could not create a new COFF section: %s", coff_errmsg (-1));
277
 
278
  /* Add a string table entry and record the offset.  */
279
  gcc_assert (file->shstrtab_stream);
280
  sh_name = file->shstrtab_stream->total_size;
281
  lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
282
 
283
  /* Initialize the section header.  */
284
  file->scn->strtab_offs = sh_name;
285
}
286
 
287
 
288
/* Begin a new COFF section named NAME in the current output file.  */
289
 
290
void
291
lto_obj_begin_section (const char *name)
292
{
293
  lto_coff_begin_section_with_type (name, 0);
294
}
295
 
296
 
297
/* Append DATA of length LEN to the current output section.  BASE is a pointer
298
   to the output page containing DATA.  It is freed once the output file has
299
   been written.  */
300
 
301
void
302
lto_obj_append_data (const void *data, size_t len, void *block)
303
{
304
  lto_coff_file *file;
305
  lto_coff_data *coff_data;
306
  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
307
 
308
  /* Grab the current output file and do some basic assertion checking.  */
309
  file = (lto_coff_file *) lto_get_current_out_file ();
310
  gcc_assert (file);
311
  gcc_assert (file->scn);
312
 
313
  coff_data = coff_newdata (file->scn);
314
  if (!coff_data)
315
    fatal_error ("could not append data to COFF section: %s", coff_errmsg (-1));
316
 
317
  coff_data->d_buf = CONST_CAST (void *, data);
318
  coff_data->d_size = len;
319
 
320
  /* Chain all data blocks (from all sections) on one singly-linked
321
     list for freeing en masse after the file is closed.  */
322
  base->ptr = (char *)file->data;
323
  file->data = base;
324
}
325
 
326
 
327
/* End the current output section.  This just does some assertion checking
328
   and sets the current output file's scn member to NULL.  */
329
 
330
void
331
lto_obj_end_section (void)
332
{
333
  lto_coff_file *file;
334
 
335
  /* Grab the current output file and validate some basic assertions.  */
336
  file = (lto_coff_file *) lto_get_current_out_file ();
337
  gcc_assert (file);
338
  gcc_assert (file->scn);
339
 
340
  file->scn = NULL;
341
}
342
 
343
 
344
/* Validate's COFF_FILE's executable header and, if cached_coff_hdr is
345
   uninitialized, caches the results.  Also records the section header string
346
   table's section index.  Returns true on success or false on failure.  */
347
 
348
static bool
349
validate_file (lto_coff_file *coff_file)
350
{
351
  size_t n, secnum;
352
  unsigned int numsections, secheaderssize, numsyms;
353
  off_t sectionsstart, symbolsstart, stringsstart;
354
  unsigned int mach, charact;
355
 
356
  /* Read and sanity check the raw header.  */
357
  n = read (coff_file->fd, &coff_file->coffhdr, sizeof (coff_file->coffhdr));
358
  if (n != sizeof (coff_file->coffhdr))
359
    {
360
      error ("not a COFF object file");
361
      return false;
362
    }
363
 
364
  mach = COFF_GET(&coff_file->coffhdr, Machine);
365
  for (n = 0; n < NUM_COFF_KNOWN_MACHINES; n++)
366
    if (mach == coff_machine_array[n])
367
      break;
368
  if (n == NUM_COFF_KNOWN_MACHINES)
369
    {
370
      error ("not a recognized COFF object file");
371
      return false;
372
    }
373
 
374
  charact = COFF_GET(&coff_file->coffhdr, Characteristics);
375
  if (COFF_NOT_CHARACTERISTICS & charact)
376
    {
377
      /* DLL, EXE or SYS file.  */
378
      error ("not a relocatable COFF object file");
379
      return false;
380
    }
381
 
382
  if (COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
383
    {
384
      /* ECOFF/XCOFF/PE+ support not implemented.  */
385
      error ("not a 32-bit COFF object file");
386
      return false;
387
    }
388
 
389
  /* It validated OK, so cached it if we don't already have one.  */
390
  if (!cached_coff_hdr_valid)
391
    {
392
      cached_coff_hdr_valid = true;
393
      memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
394
    }
395
 
396
  if (mach != COFF_GET(&cached_coff_hdr, Machine))
397
    {
398
      error ("inconsistent file architecture detected");
399
      return false;
400
    }
401
 
402
  /* Read section headers and string table? */
403
 
404
  numsections = COFF_GET(&coff_file->coffhdr, NumberOfSections);
405
  secheaderssize = numsections * sizeof (Coff_section);
406
  sectionsstart = sizeof (Coff_header) + secheaderssize;
407
  symbolsstart = COFF_GET(&coff_file->coffhdr, PointerToSymbolTable);
408
  numsyms = COFF_GET(&coff_file->coffhdr, NumberOfSymbols);
409
  stringsstart = (symbolsstart + COFF_SYMBOL_SIZE * numsyms);
410
 
411
#define CVOFFSETTTED(x) (coff_file->base.offset + (x))
412
 
413
  if (numsections <= 0 || symbolsstart <= 0 || numsyms <= 0
414
        || (CVOFFSETTTED(sectionsstart) >= coff_file->file_size)
415
        || (CVOFFSETTTED(symbolsstart) >= coff_file->file_size)
416
        || (CVOFFSETTTED(stringsstart) >= coff_file->file_size))
417
    {
418
      error ("not a valid COFF object file");
419
      return false;
420
    }
421
 
422
#undef CVOFFSETTTED
423
 
424
  /* Record start of string table.  */
425
  coff_file->strtab_offs = stringsstart;
426
 
427
  /* Validate section table entries.  */
428
  for (secnum = 0; secnum < numsections; secnum++)
429
    {
430
      Coff_section coffsec;
431
      lto_coff_section *ltosec;
432
      off_t size_raw, offs_raw, offs_relocs, offs_lines;
433
      off_t num_relocs, num_lines;
434
 
435
      n = read (coff_file->fd, &coffsec, sizeof (coffsec));
436
      if (n != sizeof (coffsec))
437
        {
438
          error ("short/missing COFF section table");
439
          return false;
440
        }
441
 
442
      size_raw = COFF_GET(&coffsec, SizeOfRawData);
443
      offs_raw = COFF_GET(&coffsec, PointerToRawData);
444
      offs_relocs = COFF_GET(&coffsec, PointerToRelocations);
445
      offs_lines = COFF_GET(&coffsec, PointerToLinenumbers);
446
      num_relocs = COFF_GET(&coffsec, NumberOfRelocations);
447
      num_lines = COFF_GET(&coffsec, NumberOfLinenumbers);
448
 
449
      if (size_raw < 0 || num_relocs < 0 || num_lines < 0
450
        || (size_raw
451
          && ((COFF_GET(&coffsec, Characteristics)
452
              & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
453
            ? (offs_raw != 0)
454
            : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
455
        || (num_relocs
456
          && (offs_relocs < sectionsstart
457
            || offs_relocs >= coff_file->file_size))
458
        || (num_lines
459
          && (offs_lines < sectionsstart
460
            || offs_lines >= coff_file->file_size)))
461
        {
462
          error ("invalid COFF section table");
463
          return false;
464
        }
465
 
466
      /* Looks ok, so record its details.  We don't read the
467
         string table or set up names yet; we'll do that when
468
         we build the hash table.  */
469
      ltosec = coff_newsection (coff_file, NULL, 0);
470
      memcpy (&ltosec->coffsec, &coffsec, sizeof (ltosec->coffsec));
471
    }
472
 
473
  return true;
474
}
475
 
476
/* Initialize COFF_FILE's executable header using cached data from previously
477
   read files.  */
478
 
479
static void
480
init_coffhdr (lto_coff_file *coff_file)
481
{
482
  gcc_assert (cached_coff_hdr_valid);
483
  memset (&coff_file->coffhdr, 0, sizeof (coff_file->coffhdr));
484
  COFF_PUT(&coff_file->coffhdr, Machine, COFF_GET(&cached_coff_hdr, Machine));
485
  COFF_PUT(&coff_file->coffhdr, Characteristics, COFF_GET(&cached_coff_hdr, Characteristics));
486
}
487
 
488
/* Open COFF file FILENAME.  If WRITABLE is true, the file is opened for write
489
   and, if necessary, created.  Otherwise, the file is opened for reading.
490
   Returns the opened file.  */
491
 
492
lto_file *
493
lto_obj_file_open (const char *filename, bool writable)
494
{
495
  lto_coff_file *coff_file;
496
  lto_file *result = NULL;
497
  off_t offset;
498
  const char *offset_p;
499
  char *fname;
500
  struct stat statbuf;
501
 
502
  offset_p = strchr (filename, '@');
503
  if (!offset_p)
504
    {
505
      fname = xstrdup (filename);
506
      offset = 0;
507
    }
508
  else
509
    {
510
      /* The file started with '@' is a file containing command line
511
         options.  Stop if it doesn't exist.  */
512
      if (offset_p == filename)
513
        fatal_error ("command line option file '%s' does not exist",
514
                     filename);
515
 
516
      fname = (char *) xmalloc (offset_p - filename + 1);
517
      memcpy (fname, filename, offset_p - filename);
518
      fname[offset_p - filename] = '\0';
519
      offset_p += 3; /* skip the @0x */
520
      offset = lto_parse_hex (offset_p);
521
    }
522
 
523
  /* Set up.  */
524
  coff_file = XCNEW (lto_coff_file);
525
  result = (lto_file *) coff_file;
526
  lto_file_init (result, fname, offset);
527
  coff_file->fd = -1;
528
 
529
  /* Open the file.  */
530
  coff_file->fd = open (fname,
531
    O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
532
 
533
  if (coff_file->fd == -1)
534
    {
535
      error ("could not open file %s", fname);
536
      goto fail;
537
    }
538
 
539
  if (stat (fname, &statbuf) < 0)
540
    {
541
      error ("could not stat file %s", fname);
542
      goto fail;
543
    }
544
 
545
  coff_file->file_size = statbuf.st_size;
546
 
547
  if (offset != 0)
548
    {
549
      char ar_tail[12];
550
      int size;
551
 
552
      /* Surely not?  */
553
      gcc_assert (!writable);
554
 
555
      /* Seek to offset, or error.  */
556
      if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
557
        {
558
          error ("could not find archive member @0x%lx", (long) offset);
559
          goto fail;
560
        }
561
 
562
      /* Now seek back 12 chars and read the tail of the AR header to
563
         find the length of the member file.  */
564
      if (lseek (coff_file->fd, -12, SEEK_CUR) < 0
565
          || read (coff_file->fd, ar_tail, 12) != 12
566
          || lseek (coff_file->fd, 0, SEEK_CUR) != (ssize_t) offset
567
          || ar_tail[10] != '`' || ar_tail[11] != '\n')
568
        {
569
          error ("could not find archive header @0x%lx", (long) offset);
570
          goto fail;
571
        }
572
 
573
      ar_tail[11] = 0;
574
      if (sscanf (ar_tail, "%d", &size) != 1)
575
        {
576
          error ("invalid archive header @0x%lx", (long) offset);
577
          goto fail;
578
        }
579
      coff_file->file_size = size;
580
    }
581
 
582
  if (writable)
583
    {
584
      init_coffhdr (coff_file);
585
      coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
586
    }
587
  else
588
    if (!validate_file (coff_file))
589
      goto fail;
590
 
591
  return result;
592
 
593
 fail:
594
  if (result)
595
    lto_obj_file_close (result);
596
  return NULL;
597
}
598
 
599
 
600
/* Close COFF file FILE and clean up any associated data structures.  If FILE
601
   was opened for writing, the file's COFF data is written at this time, and
602
   any cached data buffers are freed.  Return TRUE if there was an error.  */
603
 
604
static bool
605
coff_write_object_file (lto_coff_file *coff_file)
606
{
607
  lto_coff_section *cursec, *stringsec;
608
  lto_coff_data *data;
609
  size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
610
  bool write_err = false;
611
  int secnum;
612
 
613
  /* Infer whether this file was opened for reading or writing from the
614
     presence or absense of an initialised stream for the string table;
615
     do nothing if it was opened for reading.  */
616
  if (!coff_file->shstrtab_stream)
617
    return false;
618
  else
619
    {
620
      /* Write the COFF string table into a dummy new section that
621
         we will not write a header for.  */
622
      lto_file *old_file = lto_set_current_out_file (&coff_file->base);
623
      /* This recursively feeds in the data to a new section.  */
624
      lto_coff_begin_section_with_type (".strtab", 1);
625
      lto_write_stream (coff_file->shstrtab_stream);
626
      lto_obj_end_section ();
627
      lto_set_current_out_file (old_file);
628
      free (coff_file->shstrtab_stream);
629
    }
630
 
631
  /* Layout the file.  Count sections (not dummy string section) and calculate
632
     data size for all of them.  */
633
  numsections = 0;
634
  totalsecsize = 0;
635
  stringssize = 0;
636
  stringsec = NULL;
637
  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
638
    {
639
      lto_coff_data *data;
640
      size_t cursecsize;
641
      cursecsize = 0;
642
      COFF_FOR_ALL_DATA(cursec,data)
643
        cursecsize += data->d_size;
644
      if (cursec->type == 0)
645
        {
646
          ++numsections;
647
          totalsecsize += COFF_ALIGN(cursecsize);
648
#if COFF_ALIGNMENT > 1
649
          cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
650
#endif
651
        }
652
      else
653
        {
654
          stringssize = cursecsize;
655
          stringsec = cursec;
656
        }
657
      COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
658
    }
659
 
660
  /* There is a file symbol and a section symbol per section,
661
     and each of these has a single auxiliary symbol following.  */
662
  numsyms = 2 * (1 + numsections);
663
 
664
  /* Great!  Now we have enough info to fill out the file header.  */
665
  COFF_PUT(&coff_file->coffhdr, NumberOfSections, numsections);
666
  COFF_PUT(&coff_file->coffhdr, NumberOfSymbols, numsyms);
667
  COFF_PUT(&coff_file->coffhdr, PointerToSymbolTable, sizeof (Coff_header)
668
                + numsections * sizeof (Coff_section) + totalsecsize);
669
  /* The remaining members were initialised to zero or copied from
670
     a cached header, so we leave them alone here.  */
671
 
672
  /* Now position all the sections, and fill out their headers.  */
673
  fileoffset = sizeof (Coff_header) + numsections * sizeof (Coff_section);
674
  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
675
    {
676
      /* Skip dummy string section.  */
677
      if (cursec->type == 1)
678
        continue;
679
      COFF_PUT(&cursec->coffsec, PointerToRawData, fileoffset);
680
      fileoffset += COFF_ALIGN (COFF_GET(&cursec->coffsec, SizeOfRawData));
681
      COFF_PUT(&cursec->coffsec, Characteristics, COFF_SECTION_CHARACTERISTICS);
682
      snprintf ((char *)&cursec->coffsec.Name[0], 8, "/%d", cursec->strtab_offs + 4);
683
    }
684
 
685
  /* We can write the data now.  As there's no way to indicate an error return
686
     from this hook, error handling is limited to not wasting our time doing
687
     any more writes in the event that any one fails.  */
688
 
689
  /* Write the COFF header.  */
690
  write_err = (write (coff_file->fd, &coff_file->coffhdr,
691
                sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
692
 
693
  /* Write the COFF section headers.  */
694
  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
695
    if (cursec->type == 1)      /* Skip dummy string section.  */
696
        continue;
697
    else if (!write_err)
698
      write_err = (write (coff_file->fd, &cursec->coffsec,
699
                sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
700
    else
701
      break;
702
 
703
  /* Write the COFF sections.  */
704
  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
705
    {
706
#if COFF_ALIGNMENT > 1
707
      static const char padzeros[COFF_ALIGNMENT] = { 0 };
708
#endif
709
      /* Skip dummy string section.  */
710
      if (cursec->type == 1)
711
        continue;
712
      COFF_FOR_ALL_DATA(cursec, data)
713
        if (!write_err)
714
          write_err = (write (coff_file->fd, data->d_buf, data->d_size)
715
                != data->d_size);
716
        else
717
          break;
718
#if COFF_ALIGNMENT > 1
719
      if (!write_err && cursec->pad_needed)
720
        write_err = (write (coff_file->fd, padzeros, cursec->pad_needed)
721
                != cursec->pad_needed);
722
#endif
723
    }
724
 
725
  /* Write the COFF symbol table.  */
726
  if (!write_err)
727
    {
728
      union
729
        {
730
          Coff_symbol sym;
731
          Coff_aux_sym_file file;
732
          Coff_aux_sym_section sec;
733
        } symbols[2];
734
      memset (&symbols[0], 0, sizeof (symbols));
735
      strcpy ((char *) &symbols[0].sym.Name[0], ".file");
736
      COFF_PUT(&symbols[0].sym, SectionNumber, IMAGE_SYM_DEBUG);
737
      COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
738
      symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_FILE;
739
      symbols[0].sym.NumberOfAuxSymbols[0] = 1;
740
      snprintf ((char *)symbols[1].file.FileName,
741
                sizeof (symbols[1].file.FileName),
742
                "%s", lbasename (coff_file->base.filename));
743
      write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
744
                != (2 * COFF_SYMBOL_SIZE));
745
 
746
      /* Set up constant parts for section sym loop.  */
747
      memset (&symbols[0], 0, sizeof (symbols));
748
      COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
749
      symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
750
      symbols[0].sym.NumberOfAuxSymbols[0] = 1;
751
 
752
      secnum = 1;
753
      if (!write_err)
754
        COFF_FOR_ALL_SECTIONS(coff_file, cursec)
755
          {
756
            /* Skip dummy string section.  */
757
            if (cursec->type == 1)
758
              continue;
759
            /* Reuse section name string for section symbol name.  */
760
            COFF_PUT_NDXSZ(&symbols[0].sym, Name, 0, 0, 4);
761
            COFF_PUT_NDXSZ(&symbols[0].sym, Name, cursec->strtab_offs + 4, 4, 4);
762
            COFF_PUT(&symbols[0].sym, SectionNumber, secnum++);
763
            COFF_PUT(&symbols[1].sec, Length,
764
                        COFF_GET(&cursec->coffsec, SizeOfRawData));
765
            if (!write_err)
766
              write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
767
                        != (2 * COFF_SYMBOL_SIZE));
768
            else
769
              break;
770
          }
771
    }
772
 
773
  /* Write the COFF string table.  */
774
  if (!write_err)
775
    {
776
      unsigned char outlen[4];
777
      COFF_PUT4(outlen, stringssize + 4);
778
      if (!write_err)
779
        write_err = (write (coff_file->fd, outlen, 4) != 4);
780
      if (stringsec)
781
        COFF_FOR_ALL_DATA(stringsec, data)
782
          if (!write_err)
783
        write_err = (write (coff_file->fd, data->d_buf, data->d_size)
784
                        != data->d_size);
785
        else
786
          break;
787
    }
788
 
789
  return write_err;
790
}
791
 
792
/* Close COFF file FILE and clean up any associated data structures.  If FILE
793
   was opened for writing, the file's COFF data is written at this time, and
794
   any cached data buffers are freed.  */
795
 
796
void
797
lto_obj_file_close (lto_file *file)
798
{
799
  lto_coff_file *coff_file = (lto_coff_file *) file;
800
  struct lto_char_ptr_base *cur, *tmp;
801
  lto_coff_section *cursec, *nextsec;
802
  bool write_err = false;
803
 
804
  /* Write the COFF string table into a dummy new section that
805
     we will not write a header for.  */
806
  if (coff_file->shstrtab_stream)
807
    coff_write_object_file (coff_file);
808
 
809
  /* Close the file, we're done.  */
810
  if (coff_file->fd != -1)
811
    close (coff_file->fd);
812
 
813
  /* Free any data buffers.  */
814
  cur = coff_file->data;
815
  while (cur)
816
    {
817
      tmp = cur;
818
      cur = (struct lto_char_ptr_base *) cur->ptr;
819
      free (tmp);
820
    }
821
 
822
  /* Free any sections and their data chains.  */
823
  cursec = coff_file->section_chain;
824
  while (cursec)
825
    {
826
      lto_coff_data *curdata, *nextdata;
827
      nextsec = cursec->next;
828
      curdata = cursec->data_chain;
829
      while (curdata)
830
        {
831
          nextdata = curdata->next;
832
          free (curdata);
833
          curdata = nextdata;
834
        }
835
      free (cursec);
836
      cursec = nextsec;
837
    }
838
 
839
  free (file);
840
 
841
  /* If there was an error, mention it.  */
842
  if (write_err)
843
    error ("I/O error writing COFF output file");
844
}
845
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.