~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/bfd/elf32-sh-symbian.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Renesas / SuperH specific support for Symbian 32-bit ELF files
 
2
   Copyright 2004, 2005, 2006, 2007, 2008
 
3
   Free Software Foundation, Inc.
 
4
   Contributed by Red Hat
 
5
 
 
6
   This file is part of BFD, the Binary File Descriptor library.
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program; if not, write to the Free Software
 
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
 
21
   MA 02110-1301, USA.  */
 
22
 
 
23
 
 
24
/* Stop elf32-sh.c from defining any target vectors.  */
 
25
#define SH_TARGET_ALREADY_DEFINED
 
26
#define sh_find_elf_flags           sh_symbian_find_elf_flags
 
27
#define sh_elf_get_flags_from_mach  sh_symbian_elf_get_flags_from_mach
 
28
#include "elf32-sh.c"
 
29
 
 
30
 
 
31
//#define SYMBIAN_DEBUG 1
 
32
#define SYMBIAN_DEBUG 0
 
33
 
 
34
#define DIRECTIVE_HEADER        "#<SYMEDIT>#\n"
 
35
#define DIRECTIVE_IMPORT        "IMPORT "
 
36
#define DIRECTIVE_EXPORT        "EXPORT "
 
37
#define DIRECTIVE_AS            "AS "
 
38
 
 
39
/* Macro to advance 's' until either it reaches 'e' or the
 
40
   character pointed to by 's' is equal to 'c'.  If 'e' is
 
41
   reached and SYMBIAN_DEBUG is enabled then the error message 'm'
 
42
   is displayed.  */
 
43
#define SKIP_UNTIL(s,e,c,m)                                     \
 
44
  do                                                            \
 
45
    {                                                           \
 
46
      while (s < e && *s != c)                                  \
 
47
        ++ s;                                                   \
 
48
      if (s >= e)                                               \
 
49
        {                                                       \
 
50
          if (SYMBIAN_DEBUG)                                    \
 
51
            fprintf (stderr, "Corrupt directive: %s\n", m);     \
 
52
          result = FALSE;                                       \
 
53
        }                                                       \
 
54
    }                                                           \
 
55
  while (0);                                                    \
 
56
  if (!result)                                                  \
 
57
     break;
 
58
 
 
59
/* Like SKIP_UNTIL except there are two terminator characters
 
60
   c1 and c2.  */
 
61
#define SKIP_UNTIL2(s,e,c1,c2,m)                                \
 
62
  do                                                            \
 
63
    {                                                           \
 
64
      while (s < e && *s != c1 && *s != c2)                     \
 
65
        ++ s;                                                   \
 
66
      if (s >= e)                                               \
 
67
        {                                                       \
 
68
          if (SYMBIAN_DEBUG)                                    \
 
69
            fprintf (stderr, "Corrupt directive: %s\n", m);     \
 
70
          result = FALSE;                                       \
 
71
        }                                                       \
 
72
    }                                                           \
 
73
  while (0);                                                    \
 
74
  if (!result)                                                  \
 
75
     break;
 
76
 
 
77
/* Macro to advance 's' until either it reaches 'e' or the
 
78
   character pointed to by 's' is not equal to 'c'.  If 'e'
 
79
   is reached and SYMBIAN_DEBUG is enabled then the error message
 
80
   'm' is displayed.  */
 
81
#define SKIP_WHILE(s,e,c,m)                                     \
 
82
  do                                                            \
 
83
    {                                                           \
 
84
      while (s < e && *s == c)                                  \
 
85
        ++ s;                                                   \
 
86
      if (s >= e)                                               \
 
87
        {                                                       \
 
88
          if (SYMBIAN_DEBUG)                                    \
 
89
            fprintf (stderr, "Corrupt directive: %s\n", m);     \
 
90
          result = FALSE;                                       \
 
91
        }                                                       \
 
92
    }                                                           \
 
93
  while (0);                                                    \
 
94
  if (!result)                                                  \
 
95
     break;
 
96
 
 
97
 
 
98
typedef struct symbol_rename
 
99
{
 
100
  struct symbol_rename *       next;
 
101
  char *                       current_name;
 
102
  char *                       new_name;
 
103
  struct elf_link_hash_entry * current_hash;
 
104
  unsigned long                new_symndx;
 
105
}
 
106
symbol_rename;
 
107
 
 
108
static symbol_rename * rename_list = NULL;
 
109
 
 
110
/* Accumulate a list of symbols to be renamed.  */
 
111
 
 
112
static bfd_boolean
 
113
sh_symbian_import_as (struct bfd_link_info *info, bfd * abfd,
 
114
                      char * current_name, char * new_name)
 
115
{
 
116
  struct elf_link_hash_entry * new_hash;
 
117
  symbol_rename * node;
 
118
 
 
119
  if (SYMBIAN_DEBUG)
 
120
    fprintf (stderr, "IMPORT '%s' AS '%s'\n", current_name, new_name);
 
121
 
 
122
  for (node = rename_list; node; node = node->next)
 
123
    if (strcmp (node->current_name, current_name) == 0)
 
124
      {
 
125
        if (strcmp (node->new_name, new_name) == 0)
 
126
          /* Already added to rename list.  */
 
127
          return TRUE;
 
128
 
 
129
        bfd_set_error (bfd_error_invalid_operation);
 
130
        _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous IMPORT AS"),
 
131
                            abfd, current_name);
 
132
        return FALSE;
 
133
      }
 
134
 
 
135
  if ((node = bfd_malloc (sizeof * node)) == NULL)
 
136
    {
 
137
      if (SYMBIAN_DEBUG)
 
138
        fprintf (stderr, "IMPORT AS: No mem for new rename node\n");
 
139
      return FALSE;
 
140
    }
 
141
 
 
142
  if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL)
 
143
    {
 
144
      if (SYMBIAN_DEBUG)
 
145
        fprintf (stderr, "IMPORT AS: No mem for current name field in rename node\n");
 
146
      free (node);
 
147
      return FALSE;
 
148
    }
 
149
  else
 
150
    strcpy (node->current_name, current_name);
 
151
 
 
152
  if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL)
 
153
    {
 
154
      if (SYMBIAN_DEBUG)
 
155
        fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n");
 
156
      free (node->current_name);
 
157
      free (node);
 
158
      return FALSE;
 
159
    }
 
160
  else
 
161
    strcpy (node->new_name, new_name);
 
162
 
 
163
  node->next = rename_list;
 
164
  node->current_hash = NULL;
 
165
  node->new_symndx = 0;
 
166
  rename_list = node;
 
167
 
 
168
  new_hash = elf_link_hash_lookup (elf_hash_table (info), node->new_name, TRUE, FALSE, TRUE);
 
169
  bfd_elf_link_record_dynamic_symbol (info, new_hash);
 
170
  if (new_hash->root.type == bfd_link_hash_new)
 
171
    new_hash->root.type = bfd_link_hash_undefined;
 
172
 
 
173
  return TRUE;
 
174
}
 
175
 
 
176
 
 
177
static bfd_boolean
 
178
sh_symbian_import (bfd * abfd ATTRIBUTE_UNUSED, char * name)
 
179
{
 
180
  if (SYMBIAN_DEBUG)
 
181
    fprintf (stderr, "IMPORT '%s'\n", name);
 
182
 
 
183
  /* XXX: Generate an import somehow ?  */
 
184
 
 
185
  return TRUE;
 
186
}
 
187
 
 
188
static bfd_boolean
 
189
sh_symbian_export (bfd * abfd ATTRIBUTE_UNUSED, char * name)
 
190
{
 
191
  if (SYMBIAN_DEBUG)
 
192
    fprintf (stderr, "EXPORT '%s'\n", name);
 
193
 
 
194
  /* XXX: Generate an export somehow ?  */
 
195
 
 
196
  return TRUE;
 
197
}
 
198
 
 
199
/* Process any magic embedded commands in the .directive. section.
 
200
   Returns TRUE upon sucecss, but if it fails it sets bfd_error and
 
201
   returns FALSE.  */
 
202
 
 
203
static bfd_boolean
 
204
sh_symbian_process_embedded_commands (struct bfd_link_info *info, bfd * abfd,
 
205
                                      asection * sec, bfd_byte * contents)
 
206
{
 
207
  char *s;
 
208
  char *e;
 
209
  bfd_boolean result = TRUE;
 
210
  bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
 
211
 
 
212
  for (s = (char *) contents, e = s + sz; s < e;)
 
213
    {
 
214
      char * directive = s;
 
215
 
 
216
      switch (*s)
 
217
        {
 
218
          /* I want to use "case DIRECTIVE_HEADER [0]:" here but gcc won't let me :-(  */
 
219
        case '#':
 
220
          if (strcmp (s, DIRECTIVE_HEADER))
 
221
            result = FALSE;
 
222
          else
 
223
            /* Just ignore the header.
 
224
               XXX: Strictly speaking we ought to check that the header
 
225
               is present and that it is the first thing in the file.  */
 
226
            s += strlen (DIRECTIVE_HEADER) + 1;
 
227
          break;
 
228
 
 
229
        case 'I':
 
230
          if (! CONST_STRNEQ (s, DIRECTIVE_IMPORT))
 
231
            result = FALSE;
 
232
          else
 
233
            {
 
234
              char * new_name;
 
235
              char * new_name_end;
 
236
              char   name_end_char;
 
237
 
 
238
              /* Skip the IMPORT directive.  */
 
239
              s += strlen (DIRECTIVE_IMPORT);
 
240
 
 
241
              new_name = s;
 
242
              /* Find the end of the new name.  */
 
243
              while (s < e && *s != ' ' && *s != '\n')
 
244
                ++ s;
 
245
              if (s >= e)
 
246
                {
 
247
                  /* We have reached the end of the .directive section
 
248
                     without encountering a string terminator.  This is
 
249
                     allowed for IMPORT directives.  */
 
250
                  new_name_end   = e - 1;
 
251
                  name_end_char  = * new_name_end;
 
252
                  * new_name_end = 0;
 
253
                  result = sh_symbian_import (abfd, new_name);
 
254
                  * new_name_end = name_end_char;
 
255
                  break;
 
256
                }
 
257
 
 
258
              /* Remember where the name ends.  */
 
259
              new_name_end = s;
 
260
              /* Skip any whitespace before the 'AS'.  */
 
261
              SKIP_WHILE (s, e, ' ', "IMPORT: Name just followed by spaces");
 
262
              /* Terminate the new name.  (Do this after skiping...)  */
 
263
              name_end_char = * new_name_end;
 
264
              * new_name_end = 0;
 
265
 
 
266
              /* Check to see if 'AS '... is present.  If so we have an
 
267
                 IMPORT AS directive, otherwise we have an IMPORT directive.  */
 
268
              if (! CONST_STRNEQ (s, DIRECTIVE_AS))
 
269
                {
 
270
                  /* Skip the new-line at the end of the name.  */
 
271
                  if (SYMBIAN_DEBUG && name_end_char != '\n')
 
272
                    fprintf (stderr, "IMPORT: No newline at end of directive\n");
 
273
                  else
 
274
                    s ++;
 
275
 
 
276
                  result = sh_symbian_import (abfd, new_name);
 
277
 
 
278
                  /* Skip past the NUL character.  */
 
279
                  if (* s ++ != 0)
 
280
                    {
 
281
                      if (SYMBIAN_DEBUG)
 
282
                        fprintf (stderr, "IMPORT: No NUL at end of directive\n");
 
283
                    }
 
284
                }
 
285
              else
 
286
                {
 
287
                  char * current_name;
 
288
                  char * current_name_end;
 
289
                  char   current_name_end_char;
 
290
 
 
291
                  /* Skip the 'AS '.  */
 
292
                  s += strlen (DIRECTIVE_AS);
 
293
                  /* Skip any white space after the 'AS '.  */
 
294
                  SKIP_WHILE (s, e, ' ', "IMPORT AS: Nothing after AS");
 
295
                  current_name = s;
 
296
                  /* Find the end of the current name.  */
 
297
                  SKIP_UNTIL2 (s, e, ' ', '\n', "IMPORT AS: No newline at the end of the current name");
 
298
                  /* Skip (backwards) over spaces at the end of the current name.  */
 
299
                  current_name_end = s;
 
300
                  current_name_end_char = * current_name_end;
 
301
 
 
302
                  SKIP_WHILE (s, e, ' ', "IMPORT AS: Current name just followed by spaces");
 
303
                  /* Skip past the newline character.  */
 
304
                  if (* s ++ != '\n')
 
305
                    if (SYMBIAN_DEBUG)
 
306
                      fprintf (stderr, "IMPORT AS: No newline at end of directive\n");
 
307
 
 
308
                  /* Terminate the current name after having performed the skips.  */
 
309
                  * current_name_end = 0;
 
310
 
 
311
                  result = sh_symbian_import_as (info, abfd, current_name, new_name);
 
312
 
 
313
                  /* The next character should be a NUL.  */
 
314
                  if (* s != 0)
 
315
                    {
 
316
                      if (SYMBIAN_DEBUG)
 
317
                        fprintf (stderr, "IMPORT AS: Junk at end of directive\n");
 
318
                      result = FALSE;
 
319
                    }
 
320
                  s ++;
 
321
 
 
322
                  * current_name_end = current_name_end_char;
 
323
                }
 
324
 
 
325
              /* Restore the characters we overwrote, since
 
326
                 the .directive section will be emitted.  */
 
327
              * new_name_end = name_end_char;
 
328
            }
 
329
          break;
 
330
 
 
331
        case 'E':
 
332
          if (! CONST_STRNEQ (s, DIRECTIVE_EXPORT))
 
333
            result = FALSE;
 
334
          else
 
335
            {
 
336
              char * name;
 
337
              char * name_end;
 
338
              char   name_end_char;
 
339
 
 
340
              /* Skip the directive.  */
 
341
              s += strlen (DIRECTIVE_EXPORT);
 
342
              name = s;
 
343
              /* Find the end of the name to be exported.  */
 
344
              SKIP_UNTIL (s, e, '\n', "EXPORT: no newline at end of directive");
 
345
              /* Skip (backwards) over spaces at end of exported name.  */
 
346
              for (name_end = s; name_end[-1] == ' '; name_end --)
 
347
                ;
 
348
              /* name_end now points at the first character after the
 
349
                 end of the exported name, so we can termiante it  */
 
350
              name_end_char = * name_end;
 
351
              * name_end = 0;
 
352
              /* Skip passed the newline character.  */
 
353
              s ++;
 
354
 
 
355
              result = sh_symbian_export (abfd, name);
 
356
 
 
357
              /* The next character should be a NUL.  */
 
358
              if (* s != 0)
 
359
                {
 
360
                  if (SYMBIAN_DEBUG)
 
361
                    fprintf (stderr, "EXPORT: Junk at end of directive\n");
 
362
                  result = FALSE;
 
363
                }
 
364
              s++;
 
365
 
 
366
              /* Restore the character we deleted.  */
 
367
              * name_end = name_end_char;
 
368
            }
 
369
          break;
 
370
 
 
371
        default:
 
372
          result = FALSE;
 
373
          break;
 
374
        }
 
375
 
 
376
      if (! result)
 
377
        {
 
378
          if (SYMBIAN_DEBUG)
 
379
            fprintf (stderr, "offset into .directive section: %ld\n",
 
380
                     (long) (directive - (char *) contents));
 
381
 
 
382
          bfd_set_error (bfd_error_invalid_operation);
 
383
          _bfd_error_handler (_("%B: Unrecognised .directive command: %s"),
 
384
                              abfd, directive);
 
385
          break;
 
386
        }
 
387
    }
 
388
 
 
389
  return result;
 
390
}
 
391
 
 
392
 
 
393
/* Scan a bfd for a .directive section, and if found process it.
 
394
   Returns TRUE upon success, FALSE otherwise.  */
 
395
 
 
396
static bfd_boolean
 
397
sh_symbian_process_directives (bfd *abfd, struct bfd_link_info *info)
 
398
{
 
399
  bfd_boolean result = FALSE;
 
400
  bfd_byte *  contents;
 
401
  asection *  sec = bfd_get_section_by_name (abfd, ".directive");
 
402
  bfd_size_type sz;
 
403
 
 
404
  if (!sec)
 
405
    return TRUE;
 
406
 
 
407
  sz = sec->rawsize ? sec->rawsize : sec->size;
 
408
  contents = bfd_malloc (sz);
 
409
 
 
410
  if (!contents)
 
411
    bfd_set_error (bfd_error_no_memory);
 
412
  else
 
413
    {
 
414
      if (bfd_get_section_contents (abfd, sec, contents, 0, sz))
 
415
        result = sh_symbian_process_embedded_commands (info, abfd, sec, contents);
 
416
      free (contents);
 
417
    }
 
418
 
 
419
  return result;
 
420
}
 
421
 
 
422
/* Intercept the normal sh_relocate_section() function
 
423
   and magle the relocs to allow for symbol renaming.  */
 
424
 
 
425
static bfd_boolean
 
426
sh_symbian_relocate_section (bfd *                  output_bfd,
 
427
                             struct bfd_link_info * info,
 
428
                             bfd *                  input_bfd,
 
429
                             asection *             input_section,
 
430
                             bfd_byte *             contents,
 
431
                             Elf_Internal_Rela *    relocs,
 
432
                             Elf_Internal_Sym *     local_syms,
 
433
                             asection **            local_sections)
 
434
{
 
435
  /* When performing a final link we implement the IMPORT AS directives.  */
 
436
  if (!info->relocatable)
 
437
    {
 
438
      Elf_Internal_Rela *            rel;
 
439
      Elf_Internal_Rela *            relend;
 
440
      Elf_Internal_Shdr *            symtab_hdr;
 
441
      struct elf_link_hash_entry **  sym_hashes;
 
442
      struct elf_link_hash_entry **  sym_hashes_end;
 
443
      struct elf_link_hash_table *   hash_table;
 
444
      symbol_rename *                ptr;
 
445
      bfd_size_type                  num_global_syms;
 
446
      unsigned long                  num_local_syms;
 
447
 
 
448
      BFD_ASSERT (! elf_bad_symtab (input_bfd));
 
449
 
 
450
      symtab_hdr       = & elf_tdata (input_bfd)->symtab_hdr;
 
451
      hash_table       = elf_hash_table (info);
 
452
      num_local_syms   = symtab_hdr->sh_info;
 
453
      num_global_syms  = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
 
454
      num_global_syms -= num_local_syms;
 
455
      sym_hashes       = elf_sym_hashes (input_bfd);
 
456
      sym_hashes_end   = sym_hashes + num_global_syms;
 
457
 
 
458
      /* First scan the rename table, caching the hash entry and the new index.  */
 
459
      for (ptr = rename_list; ptr; ptr = ptr->next)
 
460
        {
 
461
          struct elf_link_hash_entry *   new_hash;
 
462
          struct elf_link_hash_entry **  h;
 
463
 
 
464
          ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_name, FALSE, FALSE, TRUE);
 
465
 
 
466
          if (ptr->current_hash == NULL)
 
467
            {
 
468
              if (SYMBIAN_DEBUG)
 
469
                fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\n", ptr->current_name);
 
470
              continue;
 
471
            }
 
472
 
 
473
          new_hash = elf_link_hash_lookup (hash_table, ptr->new_name,
 
474
                                           FALSE, FALSE, TRUE);
 
475
          /* If we could not find the symbol then it is a new, undefined symbol.
 
476
             Symbian want this behaviour - ie they want to be able to rename the
 
477
             reference in a reloc from one undefined symbol to another, new and
 
478
             undefined symbol.  So we create that symbol here.  */
 
479
          if (new_hash == NULL)
 
480
            {
 
481
              struct bfd_link_hash_entry *bh = NULL;
 
482
              bfd_boolean collect = get_elf_backend_data (input_bfd)->collect;
 
483
              if (_bfd_generic_link_add_one_symbol (info, input_bfd,
 
484
                                                    ptr->new_name, BSF_GLOBAL,
 
485
                                                    bfd_und_section_ptr, 0,
 
486
                                                    NULL, FALSE, collect,
 
487
                                                    &bh))
 
488
                {
 
489
                  new_hash = (struct elf_link_hash_entry *) bh;
 
490
                  new_hash->type = STT_FUNC;
 
491
                  new_hash->non_elf = 0;
 
492
 
 
493
                  if (SYMBIAN_DEBUG)
 
494
                    fprintf (stderr, "Created new symbol %s\n", ptr->new_name);
 
495
                }
 
496
            }
 
497
 
 
498
          if (new_hash == NULL)
 
499
            {
 
500
              _bfd_error_handler (_("%B: Failed to add renamed symbol %s"),
 
501
                                  input_bfd, ptr->new_name);
 
502
              continue;
 
503
            }
 
504
 
 
505
          /* Convert the new_hash value into a index into the table of symbol hashes.  */
 
506
          for (h = sym_hashes; h < sym_hashes_end; h ++)
 
507
            {
 
508
              if (* h == new_hash)
 
509
                {
 
510
                  ptr->new_symndx = h - sym_hashes + num_local_syms;
 
511
                  if (SYMBIAN_DEBUG)
 
512
                    fprintf (stderr, "Converted new hash to index of %ld\n", ptr->new_symndx);
 
513
                  break;
 
514
                }
 
515
            }
 
516
          /* If the new symbol is not in the hash table then it must be
 
517
             because it is one of the newly created undefined symbols
 
518
             manufactured above.  So we extend the sym has table here to
 
519
             include this extra symbol.  */
 
520
          if (h == sym_hashes_end)
 
521
            {
 
522
              struct elf_link_hash_entry **  new_sym_hashes;
 
523
 
 
524
              /* This is not very efficient, but it works.  */
 
525
              ++ num_global_syms;
 
526
              new_sym_hashes = bfd_alloc (input_bfd, num_global_syms * sizeof * sym_hashes);
 
527
              if (new_sym_hashes == NULL)
 
528
                {
 
529
                  if (SYMBIAN_DEBUG)
 
530
                    fprintf (stderr, "Out of memory extending hash table\n");
 
531
                  continue;
 
532
                }
 
533
              memcpy (new_sym_hashes, sym_hashes, (num_global_syms - 1) * sizeof * sym_hashes);
 
534
              new_sym_hashes[num_global_syms - 1] = new_hash;
 
535
              elf_sym_hashes (input_bfd) = sym_hashes = new_sym_hashes;
 
536
              sym_hashes_end = sym_hashes + num_global_syms;
 
537
              symtab_hdr->sh_size  = (num_global_syms + num_local_syms) * sizeof (Elf32_External_Sym);
 
538
 
 
539
              ptr->new_symndx = num_global_syms - 1 + num_local_syms;
 
540
 
 
541
              if (SYMBIAN_DEBUG)
 
542
                fprintf (stderr, "Extended symbol hash table to insert new symbol as index %ld\n",
 
543
                         ptr->new_symndx);
 
544
            }
 
545
        }
 
546
 
 
547
      /* Walk the reloc list looking for references to renamed symbols.
 
548
         When we find one, we alter the index in the reloc to point to the new symbol.  */
 
549
      for (rel = relocs, relend = relocs + input_section->reloc_count;
 
550
           rel < relend;
 
551
           rel ++)
 
552
        {
 
553
          int                          r_type;
 
554
          unsigned long                r_symndx;
 
555
          struct elf_link_hash_entry * h;
 
556
 
 
557
          r_symndx = ELF32_R_SYM (rel->r_info);
 
558
          r_type = ELF32_R_TYPE (rel->r_info);
 
559
 
 
560
          /* Ignore unused relocs.  */
 
561
          if ((r_type >= (int) R_SH_GNU_VTINHERIT
 
562
               && r_type <= (int) R_SH_LABEL)
 
563
              || r_type == (int) R_SH_NONE
 
564
              || r_type < 0
 
565
              || r_type >= R_SH_max)
 
566
            continue;
 
567
 
 
568
          /* Ignore relocs against local symbols.  */
 
569
          if (r_symndx < num_local_syms)
 
570
            continue;
 
571
 
 
572
          BFD_ASSERT (r_symndx < (num_global_syms + num_local_syms));
 
573
          h = sym_hashes[r_symndx - num_local_syms];
 
574
          BFD_ASSERT (h != NULL);
 
575
 
 
576
          while (   h->root.type == bfd_link_hash_indirect
 
577
                 || h->root.type == bfd_link_hash_warning)
 
578
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
579
 
 
580
          /* If the symbol is defined there is no need to rename it.
 
581
             XXX - is this true ?  */
 
582
          if (   h->root.type == bfd_link_hash_defined
 
583
              || h->root.type == bfd_link_hash_defweak
 
584
              || h->root.type == bfd_link_hash_undefweak)
 
585
            continue;
 
586
 
 
587
          for (ptr = rename_list; ptr; ptr = ptr->next)
 
588
            if (h == ptr->current_hash)
 
589
              {
 
590
                BFD_ASSERT (ptr->new_symndx);
 
591
                if (SYMBIAN_DEBUG)
 
592
                  fprintf (stderr, "convert reloc %lx from using index %ld to using index %ld\n",
 
593
                           (unsigned long) rel->r_info,
 
594
                           (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx);
 
595
                rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type);
 
596
                break;
 
597
              }
 
598
        }
 
599
    }
 
600
 
 
601
  return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
602
                                  contents, relocs, local_syms, local_sections);
 
603
}
 
604
 
 
605
#define TARGET_LITTLE_SYM       bfd_elf32_shl_symbian_vec
 
606
#define TARGET_LITTLE_NAME      "elf32-shl-symbian"
 
607
 
 
608
#undef  elf_backend_relocate_section
 
609
#define elf_backend_relocate_section    sh_symbian_relocate_section
 
610
#undef  elf_backend_check_directives
 
611
#define elf_backend_check_directives    sh_symbian_process_directives
 
612
 
 
613
#include "elf32-target.h"