aboutsummaryrefslogtreecommitdiff
path: root/bfd/seclet.c
blob: e16fa281382d1d894942f3dcb53c7eb0fcb5129e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* This module is part of BFD */


/* The intention is that one day, all the code which uses sections
   will change and use seclets instead - maybe seglet would have been
   a better name..

   Anyway, a seclet contains enough info to be able to describe an
   area of output memory in one go.

   The only description so far catered for is that of the
   <<bfd_indirect_seclet>>, which is a select which points to a
   <<section>> and the <<asymbols>> associated with the section, so
   that relocation can be done when needed.

   One day there will be more types - they will at least migrate from
   the linker's data structures - also there could be extra stuff,
   like a bss seclet, which descibes a lump of memory as containing
   zeros compactly, without the horrible SEC_* flag cruft.


*/

#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "seclet.h"
#include "coff/internal.h"
bfd_seclet_type *
DEFUN(bfd_new_seclet,(abfd, section),
      bfd *abfd AND
      asection *section)
{
  bfd_seclet_type *n = (bfd_seclet_type *)bfd_alloc(abfd, sizeof(bfd_seclet_type));
  if (section->seclets_tail != (bfd_seclet_type *)NULL) {
      section->seclets_tail->next = n;
    }
  else
  {
    section->seclets_head = n;
  }
  section->seclets_tail = n;

  return n;
}




#define MAX_ERRORS_IN_A_ROW 10
extern bfd_error_vector_type bfd_error_vector;


void
DEFUN(rel,(abfd, seclet, output_section),
      bfd *abfd AND
      bfd_seclet_type *seclet AND
      asection *output_section)
{

  if (output_section->flags & SEC_HAS_CONTENTS 
      && !(output_section->flags & SEC_NEVER_LOAD))
  {
    bfd_byte *data = (bfd_byte *)alloca(seclet->size);
    data = bfd_get_relocated_section_contents(abfd, seclet, data);
    if(bfd_set_section_contents(abfd,
				output_section,
				data,
				seclet->offset,
				seclet->size) == false)
    {
      abort();
    }

  }
}

void
DEFUN(seclet_dump_seclet,(abfd, seclet, section),
      bfd *abfd AND
      bfd_seclet_type *seclet AND
      asection *section)
{
  switch (seclet->type) 
  {
   case bfd_indirect_seclet:
    /* The contents of this section come from another one somewhere
       else */
    rel(abfd, seclet, section);
    break;
   case bfd_fill_seclet:
    /* Fill in the section with us */
   {
     char *d = malloc(seclet->size);
     unsigned int i;
     for (i =0;  i < seclet->size; i+=2) {
       d[i] = seclet->u.fill.value >> 8;
     }
     for (i = 1; i < seclet->size; i+=2) {
       d[i] = seclet->u.fill.value ;
     }
     bfd_set_section_contents(abfd, section, d, seclet->offset, seclet->size);

   }
    break;
   default:
    abort();
  }
}

void
DEFUN(seclet_dump,(abfd),
      bfd *abfd)
{
  /* Write all the seclets on the bfd out, relocate etc according to the
     rules */

  asection *o = abfd->sections;
  while (o != (asection *)NULL) 
  {
    bfd_seclet_type *p = o->seclets_head;
    while (p != (bfd_seclet_type *)NULL) 
    {
      seclet_dump_seclet(abfd, p, o);
      p = p ->next;
    }
    o = o->next;
  }
}