00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "bfd.h"
00040 #include "sysdep.h"
00041 #include "libbfd.h"
00042 #include "bfdlink.h"
00043 #include "genlink.h"
00044 #include "coff/internal.h"
00045 #include "libcoff.h"
00046
00047 bfd_vma
00048 bfd_coff_reloc16_get_value (reloc, link_info, input_section)
00049 arelent *reloc;
00050 struct bfd_link_info *link_info;
00051 asection *input_section;
00052 {
00053 bfd_vma value;
00054 asymbol *symbol = *(reloc->sym_ptr_ptr);
00055
00056
00057
00058
00059 if (bfd_is_und_section (symbol->section)
00060 || bfd_is_com_section (symbol->section))
00061 {
00062 struct bfd_link_hash_entry *h;
00063
00064
00065
00066
00067
00068
00069 h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
00070 bfd_asymbol_name (symbol),
00071 FALSE, FALSE, TRUE);
00072 if (h != (struct bfd_link_hash_entry *) NULL
00073 && (h->type == bfd_link_hash_defined
00074 || h->type == bfd_link_hash_defweak))
00075 value = (h->u.def.value
00076 + h->u.def.section->output_section->vma
00077 + h->u.def.section->output_offset);
00078 else if (h != (struct bfd_link_hash_entry *) NULL
00079 && h->type == bfd_link_hash_common)
00080 value = h->u.c.size;
00081 else
00082 {
00083 if (!((*link_info->callbacks->undefined_symbol)
00084 (link_info, bfd_asymbol_name (symbol),
00085 input_section->owner, input_section, reloc->address,
00086 TRUE)))
00087 abort ();
00088 value = 0;
00089 }
00090 }
00091 else
00092 {
00093 value = symbol->value
00094 + symbol->section->output_offset
00095 + symbol->section->output_section->vma;
00096 }
00097
00098
00099 value += reloc->addend;
00100
00101 return value;
00102 }
00103
00104 void
00105 bfd_perform_slip (abfd, slip, input_section, value)
00106 bfd *abfd;
00107 unsigned int slip;
00108 asection *input_section;
00109 bfd_vma value;
00110 {
00111 asymbol **s;
00112
00113 s = _bfd_generic_link_get_symbols (abfd);
00114 BFD_ASSERT (s != (asymbol **) NULL);
00115
00116
00117
00118 while (*s)
00119 {
00120 asymbol *p = *s;
00121 if (p->section == input_section)
00122 {
00123
00124 if (p->value > value)
00125 {
00126 p->value -= slip;
00127 if (p->udata.p != NULL)
00128 {
00129 struct generic_link_hash_entry *h;
00130
00131 h = (struct generic_link_hash_entry *) p->udata.p;
00132 BFD_ASSERT (h->root.type == bfd_link_hash_defined
00133 || h->root.type == bfd_link_hash_defweak);
00134 h->root.u.def.value -= slip;
00135 BFD_ASSERT (h->root.u.def.value == p->value);
00136 }
00137 }
00138 }
00139 s++;
00140 }
00141 }
00142
00143 bfd_boolean
00144 bfd_coff_reloc16_relax_section (abfd, input_section, link_info, again)
00145 bfd *abfd;
00146 asection *input_section;
00147 struct bfd_link_info *link_info;
00148 bfd_boolean *again;
00149 {
00150
00151 bfd *input_bfd = input_section->owner;
00152 unsigned *shrinks;
00153 unsigned shrink = 0;
00154 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
00155 arelent **reloc_vector = NULL;
00156 long reloc_count;
00157
00158
00159
00160 *again = FALSE;
00161
00162 if (reloc_size < 0)
00163 return FALSE;
00164
00165 reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
00166 if (!reloc_vector && reloc_size > 0)
00167 return FALSE;
00168
00169
00170 reloc_count =
00171 bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
00172 _bfd_generic_link_get_symbols (input_bfd));
00173 if (reloc_count < 0)
00174 {
00175 free (reloc_vector);
00176 return FALSE;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 if (reloc_count > 0)
00195 {
00196 int another_pass = 0;
00197 bfd_size_type amt;
00198
00199
00200
00201 amt = reloc_count + 1;
00202 amt *= sizeof (unsigned);
00203 shrinks = (unsigned *) bfd_zmalloc (amt);
00204
00205
00206 do
00207 {
00208 arelent **parent;
00209 unsigned int i;
00210 long j;
00211
00212 another_pass = 0;
00213
00214 for (i = 0, parent = reloc_vector; *parent; parent++, i++)
00215 {
00216
00217
00218 shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
00219 shrinks[i], link_info);
00220
00221
00222
00223 if (shrink != shrinks[i])
00224 {
00225 another_pass = 1;
00226 for (j = i + 1; j <= reloc_count; j++)
00227 shrinks[j] += shrink - shrinks[i];
00228 }
00229 }
00230 }
00231 while (another_pass);
00232
00233 shrink = shrinks[reloc_count];
00234 free ((char *) shrinks);
00235 }
00236
00237 input_section->rawsize = input_section->size;
00238 input_section->size -= shrink;
00239 free ((char *) reloc_vector);
00240 return TRUE;
00241 }
00242
00243 bfd_byte *
00244 bfd_coff_reloc16_get_relocated_section_contents (in_abfd,
00245 link_info,
00246 link_order,
00247 data,
00248 relocatable,
00249 symbols)
00250 bfd *in_abfd;
00251 struct bfd_link_info *link_info;
00252 struct bfd_link_order *link_order;
00253 bfd_byte *data;
00254 bfd_boolean relocatable;
00255 asymbol **symbols;
00256 {
00257
00258 bfd *input_bfd = link_order->u.indirect.section->owner;
00259 asection *input_section = link_order->u.indirect.section;
00260 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
00261 arelent **reloc_vector;
00262 long reloc_count;
00263 bfd_size_type sz;
00264
00265 if (reloc_size < 0)
00266 return NULL;
00267
00268
00269 if (relocatable)
00270 return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
00271 link_order,
00272 data, relocatable,
00273 symbols);
00274
00275
00276 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
00277 if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
00278 return NULL;
00279
00280 reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
00281 if (!reloc_vector && reloc_size != 0)
00282 return NULL;
00283
00284 reloc_count = bfd_canonicalize_reloc (input_bfd,
00285 input_section,
00286 reloc_vector,
00287 symbols);
00288 if (reloc_count < 0)
00289 {
00290 free (reloc_vector);
00291 return NULL;
00292 }
00293
00294 if (reloc_count > 0)
00295 {
00296 arelent **parent = reloc_vector;
00297 arelent *reloc;
00298 unsigned int dst_address = 0;
00299 unsigned int src_address = 0;
00300 unsigned int run;
00301 unsigned int idx;
00302
00303
00304 while (dst_address < link_order->size)
00305 {
00306 reloc = *parent;
00307 if (reloc)
00308 {
00309
00310
00311
00312 run = reloc->address - src_address;
00313 parent++;
00314 }
00315 else
00316 {
00317 run = link_order->size - dst_address;
00318 }
00319
00320
00321 for (idx = 0; idx < run; idx++)
00322 data[dst_address++] = data[src_address++];
00323
00324
00325 if (reloc)
00326 {
00327 bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
00328 reloc, data, &src_address,
00329 &dst_address);
00330 }
00331 }
00332 }
00333 free ((char *) reloc_vector);
00334 return data;
00335 }