1214571Sdim/* MeP-specific support for 32-bit ELF.
2214571Sdim   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
3214571Sdim   Free Software Foundation, Inc.
4214571Sdim
5214571Sdim   This file is part of BFD, the Binary File Descriptor library.
6214571Sdim
7214571Sdim   This program is free software; you can redistribute it and/or modify
8214571Sdim   it under the terms of the GNU General Public License as published by
9214571Sdim   the Free Software Foundation; either version 2 of the License, or
10214571Sdim   (at your option) any later version.
11214571Sdim
12214571Sdim   This program is distributed in the hope that it will be useful,
13214571Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
14214571Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15214571Sdim   GNU General Public License for more details.
16214571Sdim
17214571Sdim   You should have received a copy of the GNU General Public License
18214571Sdim   along with this program; if not, write to the Free Software
19214571Sdim   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
20214571Sdim
21214571Sdim#include "sysdep.h"
22214571Sdim#include "bfd.h"
23214571Sdim#include "libbfd.h"
24214571Sdim#include "elf-bfd.h"
25214571Sdim#include "elf/mep.h"
26214571Sdim#include "libiberty.h"
27214571Sdim
28214571Sdim/* Forward declarations.  */
29214571Sdim
30214571Sdim/* Private relocation functions.  */
31214571Sdim
32214571Sdim#define MEPREL(type, size, bits, right, left, pcrel, overflow, mask) \
33214571Sdim  {(unsigned)type, right, size, bits, pcrel, left, overflow, mep_reloc, #type, FALSE, 0, mask, 0 }
34214571Sdim
35214571Sdim#define N complain_overflow_dont
36214571Sdim#define S complain_overflow_signed
37214571Sdim#define U complain_overflow_unsigned
38214571Sdim
39214571Sdimstatic bfd_reloc_status_type mep_reloc (bfd *, arelent *, struct bfd_symbol *,
40214571Sdim					void *, asection *, bfd *, char **);
41214571Sdim
42214571Sdimstatic reloc_howto_type mep_elf_howto_table [] =
43214571Sdim{
44214571Sdim  /* type, size, bits, leftshift, rightshift, pcrel, OD/OS/OU, mask.  */
45214571Sdim  MEPREL (R_MEP_NONE,     0,  0, 0, 0, 0, N, 0),
46214571Sdim  MEPREL (R_RELC,         0,  0, 0, 0, 0, N, 0),
47214571Sdim  /* MEPRELOC:HOWTO */
48214571Sdim    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
49214571Sdim  MEPREL (R_MEP_8,        0,  8, 0, 0, 0, U, 0xff),
50214571Sdim  MEPREL (R_MEP_16,       1, 16, 0, 0, 0, U, 0xffff),
51214571Sdim  MEPREL (R_MEP_32,       2, 32, 0, 0, 0, U, 0xffffffff),
52214571Sdim  MEPREL (R_MEP_PCREL8A2, 1,  8, 1, 1, 1, S, 0x00fe),
53214571Sdim  MEPREL (R_MEP_PCREL12A2,1, 12, 1, 1, 1, S, 0x0ffe),
54214571Sdim  MEPREL (R_MEP_PCREL17A2,2, 17, 0, 1, 1, S, 0x0000ffff),
55214571Sdim  MEPREL (R_MEP_PCREL24A2,2, 24, 0, 1, 1, S, 0x07f0ffff),
56214571Sdim  MEPREL (R_MEP_PCABS24A2,2, 24, 0, 1, 0, U, 0x07f0ffff),
57214571Sdim  MEPREL (R_MEP_LOW16,    2, 16, 0, 0, 0, N, 0x0000ffff),
58214571Sdim  MEPREL (R_MEP_HI16U,    2, 32, 0,16, 0, N, 0x0000ffff),
59214571Sdim  MEPREL (R_MEP_HI16S,    2, 32, 0,16, 0, N, 0x0000ffff),
60214571Sdim  MEPREL (R_MEP_GPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
61214571Sdim  MEPREL (R_MEP_TPREL,    2, 16, 0, 0, 0, S, 0x0000ffff),
62214571Sdim  MEPREL (R_MEP_TPREL7,   1,  7, 0, 0, 0, U, 0x007f),
63214571Sdim  MEPREL (R_MEP_TPREL7A2, 1,  7, 1, 1, 0, U, 0x007e),
64214571Sdim  MEPREL (R_MEP_TPREL7A4, 1,  7, 2, 2, 0, U, 0x007c),
65214571Sdim  MEPREL (R_MEP_UIMM24,   2, 24, 0, 0, 0, U, 0x00ffffff),
66214571Sdim  MEPREL (R_MEP_ADDR24A4, 2, 24, 0, 2, 0, U, 0x00fcffff),
67214571Sdim  MEPREL (R_MEP_GNU_VTINHERIT,1,  0,16,32, 0, N, 0x0000),
68214571Sdim  MEPREL (R_MEP_GNU_VTENTRY,1,  0,16,32, 0, N, 0x0000),
69214571Sdim  /* MEPRELOC:END */
70214571Sdim};
71214571Sdim
72214571Sdim#define VALID_MEP_RELOC(N) ((N) >= 0 \
73214571Sdim  && (N) < ARRAY_SIZE (mep_elf_howto_table)
74214571Sdim
75214571Sdim#undef N
76214571Sdim#undef S
77214571Sdim#undef U
78214571Sdim
79214571Sdimstatic bfd_reloc_status_type
80214571Sdimmep_reloc
81214571Sdim    (bfd *               abfd ATTRIBUTE_UNUSED,
82214571Sdim     arelent *           reloc_entry ATTRIBUTE_UNUSED,
83214571Sdim     struct bfd_symbol * symbol ATTRIBUTE_UNUSED,
84214571Sdim     void *              data ATTRIBUTE_UNUSED,
85214571Sdim     asection *          input_section ATTRIBUTE_UNUSED,
86214571Sdim     bfd *               output_bfd ATTRIBUTE_UNUSED,
87214571Sdim     char **             error_message ATTRIBUTE_UNUSED)
88214571Sdim{
89214571Sdim  return bfd_reloc_ok;
90214571Sdim}
91214571Sdim
92214571Sdim
93214571Sdim
94214571Sdim#define BFD_RELOC_MEP_NONE BFD_RELOC_NONE
95214571Sdim#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
96214571Sdim#define MAP(n) case BFD_RELOC_MEP_##n: type = R_MEP_##n; break
97214571Sdim#else
98214571Sdim#define MAP(n) case BFD_RELOC_MEP_/**/n: type = R_MEP_/**/n; break
99214571Sdim#endif
100214571Sdim
101214571Sdimstatic reloc_howto_type *
102214571Sdimmep_reloc_type_lookup
103214571Sdim    (bfd * abfd ATTRIBUTE_UNUSED,
104214571Sdim     bfd_reloc_code_real_type code)
105214571Sdim{
106214571Sdim  unsigned int type = 0;
107214571Sdim
108214571Sdim  switch (code)
109214571Sdim    {
110214571Sdim    MAP(NONE);
111214571Sdim    case BFD_RELOC_8:
112214571Sdim      type = R_MEP_8;
113214571Sdim      break;
114214571Sdim    case BFD_RELOC_16:
115214571Sdim      type = R_MEP_16;
116214571Sdim      break;
117214571Sdim    case BFD_RELOC_32:
118214571Sdim      type = R_MEP_32;
119214571Sdim      break;
120214571Sdim    case BFD_RELOC_VTABLE_ENTRY:
121214571Sdim      type = R_MEP_GNU_VTENTRY;
122214571Sdim      break;
123214571Sdim    case BFD_RELOC_VTABLE_INHERIT:
124214571Sdim      type = R_MEP_GNU_VTINHERIT;
125214571Sdim      break;
126214571Sdim    case BFD_RELOC_RELC:
127214571Sdim      type = R_RELC;
128214571Sdim      break;
129214571Sdim
130214571Sdim    /* MEPRELOC:MAP */
131214571Sdim    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
132214571Sdim    MAP(8);
133214571Sdim    MAP(16);
134214571Sdim    MAP(32);
135214571Sdim    MAP(PCREL8A2);
136214571Sdim    MAP(PCREL12A2);
137214571Sdim    MAP(PCREL17A2);
138214571Sdim    MAP(PCREL24A2);
139214571Sdim    MAP(PCABS24A2);
140214571Sdim    MAP(LOW16);
141214571Sdim    MAP(HI16U);
142214571Sdim    MAP(HI16S);
143214571Sdim    MAP(GPREL);
144214571Sdim    MAP(TPREL);
145214571Sdim    MAP(TPREL7);
146214571Sdim    MAP(TPREL7A2);
147214571Sdim    MAP(TPREL7A4);
148214571Sdim    MAP(UIMM24);
149214571Sdim    MAP(ADDR24A4);
150214571Sdim    MAP(GNU_VTINHERIT);
151214571Sdim    MAP(GNU_VTENTRY);
152214571Sdim    /* MEPRELOC:END */
153214571Sdim
154214571Sdim    default:
155214571Sdim      /* Pacify gcc -Wall.  */
156214571Sdim      fprintf (stderr, "mep: no reloc for code %d\n", code);
157214571Sdim      return NULL;
158214571Sdim    }
159214571Sdim
160214571Sdim  if (mep_elf_howto_table[type].type != type)
161214571Sdim    {
162214571Sdim      fprintf (stderr, "MeP: howto %d has type %d\n", type, mep_elf_howto_table[type].type);
163214571Sdim      abort ();
164214571Sdim    }
165214571Sdim
166214571Sdim  return mep_elf_howto_table + type;
167214571Sdim}
168214571Sdim
169214571Sdim#undef MAP
170214571Sdim
171214571Sdimstatic reloc_howto_type *
172214571Sdimmep_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
173214571Sdim{
174214571Sdim  unsigned int i;
175214571Sdim
176214571Sdim  for (i = 0;
177214571Sdim       i < sizeof (mep_elf_howto_table) / sizeof (mep_elf_howto_table[0]);
178214571Sdim       i++)
179214571Sdim    if (mep_elf_howto_table[i].name != NULL
180214571Sdim	&& strcasecmp (mep_elf_howto_table[i].name, r_name) == 0)
181214571Sdim      return &mep_elf_howto_table[i];
182214571Sdim
183214571Sdim  return NULL;
184214571Sdim}
185214571Sdim
186214571Sdim/* Perform a single relocation.  */
187214571Sdim
188214571Sdimstatic struct bfd_link_info *mep_info;
189214571Sdimstatic int warn_tp = 0, warn_sda = 0;
190214571Sdim
191214571Sdimstatic bfd_vma
192214571Sdimmep_lookup_global
193214571Sdim    (char *    name,
194214571Sdim     bfd_vma   ofs,
195214571Sdim     bfd_vma * cache,
196214571Sdim     int *     warn)
197214571Sdim{
198214571Sdim  struct bfd_link_hash_entry *h;
199214571Sdim
200214571Sdim  if (*cache || *warn)
201214571Sdim    return *cache;
202214571Sdim
203214571Sdim  h = bfd_link_hash_lookup (mep_info->hash, name, FALSE, FALSE, TRUE);
204214571Sdim  if (h == 0 || h->type != bfd_link_hash_defined)
205214571Sdim    {
206214571Sdim      *warn = ofs + 1;
207214571Sdim      return 0;
208214571Sdim    }
209214571Sdim  *cache = (h->u.def.value
210214571Sdim	  + h->u.def.section->output_section->vma
211214571Sdim	  + h->u.def.section->output_offset);
212214571Sdim  return *cache;
213214571Sdim}
214214571Sdim
215214571Sdimstatic bfd_vma
216214571Sdimmep_tpoff_base (bfd_vma ofs)
217214571Sdim{
218214571Sdim  static bfd_vma cache = 0;
219214571Sdim  return mep_lookup_global ("__tpbase", ofs, &cache, &warn_tp);
220214571Sdim}
221214571Sdim
222214571Sdimstatic bfd_vma
223214571Sdimmep_sdaoff_base (bfd_vma ofs)
224214571Sdim{
225214571Sdim  static bfd_vma cache = 0;
226214571Sdim  return mep_lookup_global ("__sdabase", ofs, &cache, &warn_sda);
227214571Sdim}
228214571Sdim
229214571Sdimstatic bfd_reloc_status_type
230214571Sdimmep_final_link_relocate
231214571Sdim    (reloc_howto_type *  howto,
232214571Sdim     bfd *               input_bfd,
233214571Sdim     asection *          input_section,
234214571Sdim     bfd_byte *          contents,
235214571Sdim     Elf_Internal_Rela * rel,
236214571Sdim     bfd_vma             relocation)
237214571Sdim{
238214571Sdim  unsigned long u;
239214571Sdim  long s;
240214571Sdim  unsigned char *byte;
241214571Sdim  bfd_vma pc;
242214571Sdim  bfd_reloc_status_type r = bfd_reloc_ok;
243214571Sdim  int e2, e4;
244214571Sdim
245214571Sdim  if (bfd_big_endian (input_bfd))
246214571Sdim    {
247214571Sdim      e2 = 0;
248214571Sdim      e4 = 0;
249214571Sdim    }
250214571Sdim  else
251214571Sdim    {
252214571Sdim      e2 = 1;
253214571Sdim      e4 = 3;
254214571Sdim    }
255214571Sdim
256214571Sdim  pc = (input_section->output_section->vma
257214571Sdim	+ input_section->output_offset
258214571Sdim	+ rel->r_offset);
259214571Sdim
260214571Sdim  s = relocation + rel->r_addend;
261214571Sdim
262214571Sdim  byte = (unsigned char *)contents + rel->r_offset;
263214571Sdim
264214571Sdim  if (howto->type == R_MEP_PCREL24A2
265214571Sdim      && s == 0
266214571Sdim      && pc >= 0x800000)
267214571Sdim    {
268214571Sdim      /* This is an unreachable branch to an undefined weak function.
269214571Sdim	 Silently ignore it, since the opcode can't do that but should
270214571Sdim	 never be executed anyway.  */
271214571Sdim      return bfd_reloc_ok;
272214571Sdim    }
273214571Sdim
274214571Sdim  if (howto->pc_relative)
275214571Sdim    s -= pc;
276214571Sdim
277214571Sdim  u = (unsigned long) s;
278214571Sdim
279214571Sdim  switch (howto->type)
280214571Sdim    {
281214571Sdim    /* MEPRELOC:APPLY */
282214571Sdim    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */
283214571Sdim    case R_MEP_8: /* 76543210 */
284214571Sdim      if (u > 255) r = bfd_reloc_overflow;
285214571Sdim      byte[0] = (u & 0xff);
286214571Sdim      break;
287214571Sdim    case R_MEP_16: /* fedcba9876543210 */
288214571Sdim      if (u > 65535) r = bfd_reloc_overflow;
289214571Sdim      byte[0^e2] = ((u >> 8) & 0xff);
290214571Sdim      byte[1^e2] = (u & 0xff);
291214571Sdim      break;
292214571Sdim    case R_MEP_32: /* vutsrqponmlkjihgfedcba9876543210 */
293214571Sdim      byte[0^e4] = ((u >> 24) & 0xff);
294214571Sdim      byte[1^e4] = ((u >> 16) & 0xff);
295214571Sdim      byte[2^e4] = ((u >> 8) & 0xff);
296214571Sdim      byte[3^e4] = (u & 0xff);
297214571Sdim      break;
298214571Sdim    case R_MEP_PCREL8A2: /* --------7654321- */
299214571Sdim      if (-128 > s || s > 127) r = bfd_reloc_overflow;
300214571Sdim      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
301214571Sdim      break;
302214571Sdim    case R_MEP_PCREL12A2: /* ----ba987654321- */
303214571Sdim      if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
304214571Sdim      byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
305214571Sdim      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
306214571Sdim      break;
307214571Sdim    case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
308214571Sdim      if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
309214571Sdim      byte[2^e2] = ((s >> 9) & 0xff);
310214571Sdim      byte[3^e2] = ((s >> 1) & 0xff);
311214571Sdim      break;
312214571Sdim    case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
313214571Sdim      if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
314214571Sdim      byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
315214571Sdim      byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
316214571Sdim      byte[2^e2] = ((s >> 16) & 0xff);
317214571Sdim      byte[3^e2] = ((s >> 8) & 0xff);
318214571Sdim      break;
319214571Sdim    case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
320214571Sdim      if (u > 16777215) r = bfd_reloc_overflow;
321214571Sdim      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
322214571Sdim      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
323214571Sdim      byte[2^e2] = ((u >> 16) & 0xff);
324214571Sdim      byte[3^e2] = ((u >> 8) & 0xff);
325214571Sdim      break;
326214571Sdim    case R_MEP_LOW16: /* ----------------fedcba9876543210 */
327214571Sdim      byte[2^e2] = ((u >> 8) & 0xff);
328214571Sdim      byte[3^e2] = (u & 0xff);
329214571Sdim      break;
330214571Sdim    case R_MEP_HI16U: /* ----------------vutsrqponmlkjihg */
331214571Sdim      byte[2^e2] = ((u >> 24) & 0xff);
332214571Sdim      byte[3^e2] = ((u >> 16) & 0xff);
333214571Sdim      break;
334214571Sdim    case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
335214571Sdim      byte[2^e2] = ((s >> 24) & 0xff);
336214571Sdim      byte[3^e2] = ((s >> 16) & 0xff);
337214571Sdim      break;
338214571Sdim    case R_MEP_GPREL: /* ----------------fedcba9876543210 */
339214571Sdim      s -= mep_sdaoff_base(rel->r_offset);
340214571Sdim      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
341214571Sdim      byte[2^e2] = ((s >> 8) & 0xff);
342214571Sdim      byte[3^e2] = (s & 0xff);
343214571Sdim      break;
344214571Sdim    case R_MEP_TPREL: /* ----------------fedcba9876543210 */
345214571Sdim      s -= mep_tpoff_base(rel->r_offset);
346214571Sdim      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
347214571Sdim      byte[2^e2] = ((s >> 8) & 0xff);
348214571Sdim      byte[3^e2] = (s & 0xff);
349214571Sdim      break;
350214571Sdim    case R_MEP_TPREL7: /* ---------6543210 */
351214571Sdim      u -= mep_tpoff_base(rel->r_offset);
352214571Sdim      if (u > 127) r = bfd_reloc_overflow;
353214571Sdim      byte[1^e2] = (byte[1^e2] & 0x80) | (u & 0x7f);
354214571Sdim      break;
355214571Sdim    case R_MEP_TPREL7A2: /* ---------654321- */
356214571Sdim      u -= mep_tpoff_base(rel->r_offset);
357214571Sdim      if (u > 127) r = bfd_reloc_overflow;
358214571Sdim      byte[1^e2] = (byte[1^e2] & 0x81) | (u & 0x7e);
359214571Sdim      break;
360214571Sdim    case R_MEP_TPREL7A4: /* ---------65432-- */
361214571Sdim      u -= mep_tpoff_base(rel->r_offset);
362214571Sdim      if (u > 127) r = bfd_reloc_overflow;
363214571Sdim      byte[1^e2] = (byte[1^e2] & 0x83) | (u & 0x7c);
364214571Sdim      break;
365214571Sdim    case R_MEP_UIMM24: /* --------76543210nmlkjihgfedcba98 */
366214571Sdim      if (u > 16777215) r = bfd_reloc_overflow;
367214571Sdim      byte[1^e2] = (u & 0xff);
368214571Sdim      byte[2^e2] = ((u >> 16) & 0xff);
369214571Sdim      byte[3^e2] = ((u >> 8) & 0xff);
370214571Sdim      break;
371214571Sdim    case R_MEP_ADDR24A4: /* --------765432--nmlkjihgfedcba98 */
372214571Sdim      if (u > 16777215) r = bfd_reloc_overflow;
373214571Sdim      byte[1^e2] = (byte[1^e2] & 0x03) | (u & 0xfc);
374214571Sdim      byte[2^e2] = ((u >> 16) & 0xff);
375214571Sdim      byte[3^e2] = ((u >> 8) & 0xff);
376214571Sdim      break;
377214571Sdim    case R_MEP_GNU_VTINHERIT: /* ---------------- */
378214571Sdim      break;
379214571Sdim    case R_MEP_GNU_VTENTRY: /* ---------------- */
380214571Sdim      break;
381214571Sdim    /* MEPRELOC:END */
382214571Sdim    default:
383214571Sdim      abort ();
384214571Sdim    }
385214571Sdim
386214571Sdim  return r;
387214571Sdim}
388214571Sdim
389214571Sdim/* Set the howto pointer for a MEP ELF reloc.  */
390214571Sdim
391214571Sdimstatic void
392214571Sdimmep_info_to_howto_rela
393214571Sdim    (bfd *               abfd ATTRIBUTE_UNUSED,
394214571Sdim     arelent *           cache_ptr,
395214571Sdim     Elf_Internal_Rela * dst)
396214571Sdim{
397214571Sdim  unsigned int r_type;
398214571Sdim
399214571Sdim  r_type = ELF32_R_TYPE (dst->r_info);
400214571Sdim  cache_ptr->howto = & mep_elf_howto_table [r_type];
401214571Sdim}
402214571Sdim
403214571Sdim/* Look through the relocs for a section during the first phase.
404214571Sdim   Since we don't do .gots or .plts, we just need to consider the
405214571Sdim   virtual table relocs for gc.  */
406214571Sdim
407214571Sdimstatic bfd_boolean
408214571Sdimmep_elf_check_relocs
409214571Sdim    (bfd *                     abfd,
410214571Sdim     struct bfd_link_info *    info,
411214571Sdim     asection *                sec,
412214571Sdim     const Elf_Internal_Rela * relocs)
413214571Sdim{
414214571Sdim  Elf_Internal_Shdr *           symtab_hdr;
415214571Sdim  struct elf_link_hash_entry ** sym_hashes;
416214571Sdim  struct elf_link_hash_entry ** sym_hashes_end;
417214571Sdim  const Elf_Internal_Rela *     rel;
418214571Sdim  const Elf_Internal_Rela *     rel_end;
419214571Sdim
420214571Sdim  if (info->relocatable)
421214571Sdim    return TRUE;
422214571Sdim
423214571Sdim  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
424214571Sdim  sym_hashes = elf_sym_hashes (abfd);
425214571Sdim  sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
426214571Sdim  if (!elf_bad_symtab (abfd))
427214571Sdim    sym_hashes_end -= symtab_hdr->sh_info;
428214571Sdim
429214571Sdim  rel_end = relocs + sec->reloc_count;
430214571Sdim  for (rel = relocs; rel < rel_end; rel++)
431214571Sdim    {
432214571Sdim      struct elf_link_hash_entry *h;
433214571Sdim      unsigned long r_symndx;
434214571Sdim
435214571Sdim      r_symndx = ELF32_R_SYM (rel->r_info);
436214571Sdim      if (r_symndx < symtab_hdr->sh_info)
437214571Sdim        h = NULL;
438214571Sdim      else
439214571Sdim        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
440214571Sdim    }
441214571Sdim  return TRUE;
442214571Sdim}
443214571Sdim
444214571Sdim
445214571Sdim/* Relocate a MEP ELF section.
446214571Sdim   There is some attempt to make this function usable for many architectures,
447214571Sdim   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
448214571Sdim   if only to serve as a learning tool.
449214571Sdim
450214571Sdim   The RELOCATE_SECTION function is called by the new ELF backend linker
451214571Sdim   to handle the relocations for a section.
452214571Sdim
453214571Sdim   The relocs are always passed as Rela structures; if the section
454214571Sdim   actually uses Rel structures, the r_addend field will always be
455214571Sdim   zero.
456214571Sdim
457214571Sdim   This function is responsible for adjusting the section contents as
458214571Sdim   necessary, and (if using Rela relocs and generating a relocatable
459214571Sdim   output file) adjusting the reloc addend as necessary.
460214571Sdim
461214571Sdim   This function does not have to worry about setting the reloc
462214571Sdim   address or the reloc symbol index.
463214571Sdim
464214571Sdim   LOCAL_SYMS is a pointer to the swapped in local symbols.
465214571Sdim
466214571Sdim   LOCAL_SECTIONS is an array giving the section in the input file
467214571Sdim   corresponding to the st_shndx field of each local symbol.
468214571Sdim
469214571Sdim   The global hash table entry for the global symbols can be found
470214571Sdim   via elf_sym_hashes (input_bfd).
471214571Sdim
472214571Sdim   When generating relocatable output, this function must handle
473214571Sdim   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
474214571Sdim   going to be the section symbol corresponding to the output
475214571Sdim   section, which means that the addend must be adjusted
476214571Sdim   accordingly.  */
477214571Sdim
478214571Sdimstatic bfd_boolean
479214571Sdimmep_elf_relocate_section
480214571Sdim    (bfd *                   output_bfd ATTRIBUTE_UNUSED,
481214571Sdim     struct bfd_link_info *  info,
482214571Sdim     bfd *                   input_bfd,
483214571Sdim     asection *              input_section,
484214571Sdim     bfd_byte *              contents,
485214571Sdim     Elf_Internal_Rela *     relocs,
486214571Sdim     Elf_Internal_Sym *      local_syms,
487214571Sdim     asection **             local_sections)
488214571Sdim{
489214571Sdim  Elf_Internal_Shdr *           symtab_hdr;
490214571Sdim  struct elf_link_hash_entry ** sym_hashes;
491214571Sdim  Elf_Internal_Rela *           rel;
492214571Sdim  Elf_Internal_Rela *           relend;
493214571Sdim
494214571Sdim  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
495214571Sdim  sym_hashes = elf_sym_hashes (input_bfd);
496214571Sdim  relend     = relocs + input_section->reloc_count;
497214571Sdim
498214571Sdim  mep_info = info;
499214571Sdim
500214571Sdim  for (rel = relocs; rel < relend; rel ++)
501214571Sdim    {
502214571Sdim      reloc_howto_type *           howto;
503214571Sdim      unsigned long                r_symndx;
504214571Sdim      Elf_Internal_Sym *           sym;
505214571Sdim      asection *                   sec;
506214571Sdim      struct elf_link_hash_entry * h;
507214571Sdim      bfd_vma                      relocation;
508214571Sdim      bfd_reloc_status_type        r;
509214571Sdim      const char *                 name = NULL;
510214571Sdim      int                          r_type;
511214571Sdim
512214571Sdim      r_type = ELF32_R_TYPE (rel->r_info);
513214571Sdim
514214571Sdim      r_symndx = ELF32_R_SYM (rel->r_info);
515214571Sdim
516214571Sdim      /* Is this a complex relocation?  */
517214571Sdim      if (!info->relocatable && ELF32_R_TYPE (rel->r_info) == R_RELC)
518214571Sdim	{
519214571Sdim	  bfd_elf_perform_complex_relocation (output_bfd, info,
520214571Sdim					      input_bfd, input_section, contents,
521214571Sdim					      rel, local_syms, local_sections);
522214571Sdim	  continue;
523214571Sdim	}
524214571Sdim
525214571Sdim      howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
526214571Sdim      h      = NULL;
527214571Sdim      sym    = NULL;
528214571Sdim      sec    = NULL;
529214571Sdim
530214571Sdim      if (r_symndx < symtab_hdr->sh_info)
531214571Sdim	{
532214571Sdim	  sym = local_syms + r_symndx;
533214571Sdim	  sec = local_sections [r_symndx];
534214571Sdim	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
535214571Sdim
536214571Sdim	  name = bfd_elf_string_from_elf_section
537214571Sdim	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
538214571Sdim	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
539214571Sdim#if 0
540214571Sdim	  fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
541214571Sdim		   sec->name, name, sym->st_name,
542214571Sdim		   sec->output_section->vma, sec->output_offset,
543214571Sdim		   sym->st_value, rel->r_addend);
544214571Sdim#endif
545214571Sdim	}
546214571Sdim      else
547214571Sdim	{
548214571Sdim	  relocation = 0;
549214571Sdim	  h = sym_hashes [r_symndx];
550214571Sdim
551214571Sdim	  while (h->root.type == bfd_link_hash_indirect
552214571Sdim		 || h->root.type == bfd_link_hash_warning)
553214571Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
554214571Sdim
555214571Sdim	  name = h->root.root.string;
556214571Sdim
557214571Sdim	  if (h->root.type == bfd_link_hash_defined
558214571Sdim	      || h->root.type == bfd_link_hash_defweak)
559214571Sdim	    {
560214571Sdim	      sec = h->root.u.def.section;
561214571Sdim	      relocation = (h->root.u.def.value
562214571Sdim			    + sec->output_section->vma
563214571Sdim			    + sec->output_offset);
564214571Sdim#if 0
565214571Sdim	      fprintf (stderr,
566214571Sdim		       "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
567214571Sdim		       sec->name, name, h->root.u.def.value,
568214571Sdim		       sec->output_section->vma, sec->output_offset, relocation);
569214571Sdim#endif
570214571Sdim	    }
571214571Sdim	  else if (h->root.type == bfd_link_hash_undefweak)
572214571Sdim	    {
573214571Sdim#if 0
574214571Sdim	      fprintf (stderr, "undefined: sec: %s, name: %s\n",
575214571Sdim		       sec->name, name);
576214571Sdim#endif
577214571Sdim	    }
578214571Sdim	  else if (!info->relocatable)
579214571Sdim	    {
580214571Sdim	      if (! ((*info->callbacks->undefined_symbol)
581214571Sdim		     (info, h->root.root.string, input_bfd,
582214571Sdim		      input_section, rel->r_offset,
583214571Sdim		      (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR))))
584214571Sdim		return FALSE;
585214571Sdim#if 0
586214571Sdim	      fprintf (stderr, "unknown: name: %s\n", name);
587214571Sdim#endif
588214571Sdim	    }
589214571Sdim	}
590214571Sdim
591214571Sdim      if (sec != NULL && elf_discarded_section (sec))
592214571Sdim	{
593214571Sdim	  /* For relocs against symbols from removed linkonce sections,
594214571Sdim	     or sections discarded by a linker script, we just want the
595214571Sdim	     section contents zeroed.  Avoid any special processing.  */
596214571Sdim	  _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
597214571Sdim	  rel->r_info = 0;
598214571Sdim	  rel->r_addend = 0;
599214571Sdim	  continue;
600214571Sdim	}
601214571Sdim
602214571Sdim      if (info->relocatable)
603214571Sdim	{
604214571Sdim	  /* This is a relocatable link.  We don't have to change
605214571Sdim             anything, unless the reloc is against a section symbol,
606214571Sdim             in which case we have to adjust according to where the
607214571Sdim             section symbol winds up in the output section.  */
608214571Sdim	  if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
609214571Sdim	    rel->r_addend += sec->output_offset;
610214571Sdim	  continue;
611214571Sdim	}
612214571Sdim
613214571Sdim      switch (r_type)
614214571Sdim	{
615214571Sdim	default:
616214571Sdim	  r = mep_final_link_relocate (howto, input_bfd, input_section,
617214571Sdim					 contents, rel, relocation);
618214571Sdim	  break;
619214571Sdim	}
620214571Sdim
621214571Sdim      if (r != bfd_reloc_ok)
622214571Sdim	{
623214571Sdim	  const char * msg = (const char *) NULL;
624214571Sdim
625214571Sdim	  switch (r)
626214571Sdim	    {
627214571Sdim	    case bfd_reloc_overflow:
628214571Sdim	      r = info->callbacks->reloc_overflow
629214571Sdim		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
630214571Sdim		 input_bfd, input_section, rel->r_offset);
631214571Sdim	      break;
632214571Sdim
633214571Sdim	    case bfd_reloc_undefined:
634214571Sdim	      r = info->callbacks->undefined_symbol
635214571Sdim		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
636214571Sdim	      break;
637214571Sdim
638214571Sdim	    case bfd_reloc_outofrange:
639214571Sdim	      msg = _("internal error: out of range error");
640214571Sdim	      break;
641214571Sdim
642214571Sdim	    case bfd_reloc_notsupported:
643214571Sdim	      msg = _("internal error: unsupported relocation error");
644214571Sdim	      break;
645214571Sdim
646214571Sdim	    case bfd_reloc_dangerous:
647214571Sdim	      msg = _("internal error: dangerous relocation");
648214571Sdim	      break;
649214571Sdim
650214571Sdim	    default:
651214571Sdim	      msg = _("internal error: unknown error");
652214571Sdim	      break;
653214571Sdim	    }
654214571Sdim
655214571Sdim	  if (msg)
656214571Sdim	    r = info->callbacks->warning
657214571Sdim	      (info, msg, name, input_bfd, input_section, rel->r_offset);
658214571Sdim
659214571Sdim	  if (! r)
660214571Sdim	    return FALSE;
661214571Sdim	}
662214571Sdim    }
663214571Sdim
664214571Sdim  if (warn_tp)
665214571Sdim    info->callbacks->undefined_symbol
666214571Sdim      (info, "__tpbase", input_bfd, input_section, warn_tp-1, TRUE);
667214571Sdim  if (warn_sda)
668214571Sdim    info->callbacks->undefined_symbol
669214571Sdim      (info, "__sdabase", input_bfd, input_section, warn_sda-1, TRUE);
670214571Sdim  if (warn_sda || warn_tp)
671214571Sdim    return FALSE;
672214571Sdim
673214571Sdim  return TRUE;
674214571Sdim}
675214571Sdim
676214571Sdim
677214571Sdim/* Update the got entry reference counts for the section being
678214571Sdim   removed.  */
679214571Sdim
680214571Sdimstatic bfd_boolean
681214571Sdimmep_elf_gc_sweep_hook
682214571Sdim    (bfd *                     abfd ATTRIBUTE_UNUSED,
683214571Sdim     struct bfd_link_info *    info ATTRIBUTE_UNUSED,
684214571Sdim     asection *                sec ATTRIBUTE_UNUSED,
685214571Sdim     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
686214571Sdim{
687214571Sdim  return TRUE;
688214571Sdim}
689214571Sdim
690214571Sdim/* Return the section that should be marked against GC for a given
691214571Sdim   relocation.  */
692214571Sdim
693214571Sdimstatic asection *
694214571Sdimmep_elf_gc_mark_hook
695214571Sdim    (asection *                   sec,
696214571Sdim     struct bfd_link_info *       info ATTRIBUTE_UNUSED,
697214571Sdim     Elf_Internal_Rela *          rel,
698214571Sdim     struct elf_link_hash_entry * h,
699214571Sdim     Elf_Internal_Sym *           sym)
700214571Sdim{
701214571Sdim  if (h != NULL)
702214571Sdim    {
703214571Sdim      switch (ELF32_R_TYPE (rel->r_info))
704214571Sdim	{
705214571Sdim	default:
706214571Sdim	  switch (h->root.type)
707214571Sdim	    {
708214571Sdim	    case bfd_link_hash_defined:
709214571Sdim	    case bfd_link_hash_defweak:
710214571Sdim	      return h->root.u.def.section;
711214571Sdim
712214571Sdim	    case bfd_link_hash_common:
713214571Sdim	      return h->root.u.c.p->section;
714214571Sdim
715214571Sdim	    default:
716214571Sdim	      break;
717214571Sdim	    }
718214571Sdim	}
719214571Sdim    }
720214571Sdim  else
721214571Sdim    {
722214571Sdim      if (!(elf_bad_symtab (sec->owner)
723214571Sdim	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
724214571Sdim	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
725214571Sdim		&& sym->st_shndx != SHN_COMMON))
726214571Sdim	return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
727214571Sdim    }
728214571Sdim
729214571Sdim  return NULL;
730214571Sdim}
731214571Sdim
732214571Sdim
733214571Sdim/* Function to set the ELF flag bits.  */
734214571Sdim
735214571Sdimstatic bfd_boolean
736214571Sdimmep_elf_set_private_flags (bfd *    abfd,
737214571Sdim			   flagword flags)
738214571Sdim{
739214571Sdim  elf_elfheader (abfd)->e_flags = flags;
740214571Sdim  elf_flags_init (abfd) = TRUE;
741214571Sdim  return TRUE;
742214571Sdim}
743214571Sdim
744214571Sdimstatic bfd_boolean
745214571Sdimmep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
746214571Sdim{
747214571Sdim  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
748214571Sdim      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
749214571Sdim    return TRUE;
750214571Sdim
751214571Sdim  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
752214571Sdim  elf_flags_init (obfd) = TRUE;
753214571Sdim
754214571Sdim  /* Copy object attributes.  */
755214571Sdim  _bfd_elf_copy_obj_attributes (ibfd, obfd);
756214571Sdim
757214571Sdim  return TRUE;
758214571Sdim}
759214571Sdim
760214571Sdim/* Merge backend specific data from an object file to the output
761214571Sdim   object file when linking.  */
762214571Sdim
763214571Sdimstatic bfd_boolean
764214571Sdimmep_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
765214571Sdim{
766214571Sdim  static bfd *last_ibfd = 0;
767214571Sdim  flagword old_flags, new_flags;
768214571Sdim  flagword old_partial, new_partial;
769214571Sdim
770214571Sdim  /* Check if we have the same endianess.  */
771214571Sdim  if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
772214571Sdim    return FALSE;
773214571Sdim
774214571Sdim  new_flags = elf_elfheader (ibfd)->e_flags;
775214571Sdim  old_flags = elf_elfheader (obfd)->e_flags;
776214571Sdim
777214571Sdim#ifdef DEBUG
778214571Sdim  _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
779214571Sdim		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
780214571Sdim#endif
781214571Sdim
782214571Sdim    /* First call, no flags set.  */
783214571Sdim    if (!elf_flags_init (obfd))
784214571Sdim    {
785214571Sdim      elf_flags_init (obfd) = TRUE;
786214571Sdim      old_flags = new_flags;
787214571Sdim    }
788214571Sdim  else if ((new_flags | old_flags) & EF_MEP_LIBRARY)
789214571Sdim    {
790214571Sdim      /* Non-library flags trump library flags.  The choice doesn't really
791214571Sdim	 matter if both OLD_FLAGS and NEW_FLAGS have EF_MEP_LIBRARY set.  */
792214571Sdim      if (old_flags & EF_MEP_LIBRARY)
793214571Sdim	old_flags = new_flags;
794214571Sdim    }
795214571Sdim  else
796214571Sdim    {
797214571Sdim      /* Make sure they're for the same mach.  Allow upgrade from the "mep"
798214571Sdim	 mach.  */
799214571Sdim      new_partial = (new_flags & EF_MEP_CPU_MASK);
800214571Sdim      old_partial = (old_flags & EF_MEP_CPU_MASK);
801214571Sdim      if (new_partial == old_partial)
802214571Sdim	;
803214571Sdim      else if (new_partial == EF_MEP_CPU_MEP)
804214571Sdim	;
805214571Sdim      else if (old_partial == EF_MEP_CPU_MEP)
806214571Sdim	old_flags = (old_flags & ~EF_MEP_CPU_MASK) | new_partial;
807214571Sdim      else
808214571Sdim	{
809214571Sdim	  _bfd_error_handler (_("%B and %B are for different cores"), last_ibfd, ibfd);
810214571Sdim	  bfd_set_error (bfd_error_invalid_target);
811214571Sdim	  return FALSE;
812214571Sdim	}
813214571Sdim
814214571Sdim      /* Make sure they're for the same me_module.  Allow basic config to
815214571Sdim	 mix with any other.  */
816214571Sdim      new_partial = (new_flags & EF_MEP_INDEX_MASK);
817214571Sdim      old_partial = (old_flags & EF_MEP_INDEX_MASK);
818214571Sdim      if (new_partial == old_partial)
819214571Sdim	;
820214571Sdim      else if (new_partial == 0)
821214571Sdim	;
822214571Sdim      else if (old_partial == 0)
823214571Sdim	old_flags = (old_flags & ~EF_MEP_INDEX_MASK) | new_partial;
824214571Sdim      else
825214571Sdim	{
826214571Sdim	  _bfd_error_handler (_("%B and %B are for different configurations"), last_ibfd, ibfd);
827214571Sdim	  bfd_set_error (bfd_error_invalid_target);
828214571Sdim	  return FALSE;
829214571Sdim	}
830214571Sdim    }
831214571Sdim
832214571Sdim  elf_elfheader (obfd)->e_flags = old_flags;
833214571Sdim  last_ibfd = ibfd;
834214571Sdim  return TRUE;
835214571Sdim}
836214571Sdim
837214571Sdim/* This will be edited by the MeP configration tool.  */
838214571Sdimstatic const char * config_names[] =
839214571Sdim{
840214571Sdim  "basic"
841214571Sdim  /* start-mepcfgtool */
842214571Sdim  ,"simple"
843214571Sdim  ,"fmax"
844214571Sdim  /* end-mepcfgtool */
845214571Sdim};
846214571Sdim
847214571Sdimstatic const char * core_names[] =
848214571Sdim{
849214571Sdim  "MeP", "MeP-c2", "MeP-c3", "MeP-h1"
850214571Sdim};
851214571Sdim
852214571Sdimstatic bfd_boolean
853214571Sdimmep_elf_print_private_bfd_data (bfd * abfd, void * ptr)
854214571Sdim{
855214571Sdim  FILE *   file = (FILE *) ptr;
856214571Sdim  flagword flags, partial_flags;
857214571Sdim
858214571Sdim  BFD_ASSERT (abfd != NULL && ptr != NULL);
859214571Sdim
860214571Sdim  /* Print normal ELF private data.  */
861214571Sdim  _bfd_elf_print_private_bfd_data (abfd, ptr);
862214571Sdim
863214571Sdim  flags = elf_elfheader (abfd)->e_flags;
864214571Sdim  fprintf (file, _("private flags = 0x%lx"), (long)flags);
865214571Sdim
866214571Sdim  partial_flags = (flags & EF_MEP_CPU_MASK) >> 24;
867214571Sdim  if (partial_flags < ARRAY_SIZE (core_names))
868214571Sdim    fprintf (file, "  core: %s", core_names[(long)partial_flags]);
869214571Sdim
870214571Sdim  partial_flags = flags & EF_MEP_INDEX_MASK;
871214571Sdim  if (partial_flags < ARRAY_SIZE (config_names))
872214571Sdim    fprintf (file, "  me_module: %s", config_names[(long)partial_flags]);
873214571Sdim
874214571Sdim  fputc ('\n', file);
875214571Sdim
876214571Sdim  return TRUE;
877214571Sdim}
878214571Sdim
879214571Sdim/* Return the machine subcode from the ELF e_flags header.  */
880214571Sdim
881214571Sdimstatic int
882214571Sdimelf32_mep_machine (bfd * abfd)
883214571Sdim{
884214571Sdim  switch (elf_elfheader (abfd)->e_flags & EF_MEP_CPU_MASK)
885214571Sdim    {
886214571Sdim    default: break;
887214571Sdim    case EF_MEP_CPU_C2: return bfd_mach_mep;
888214571Sdim    case EF_MEP_CPU_C3: return bfd_mach_mep;
889214571Sdim    case EF_MEP_CPU_C4: return bfd_mach_mep;
890214571Sdim    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
891214571Sdim    }
892214571Sdim
893214571Sdim  return bfd_mach_mep;
894214571Sdim}
895214571Sdim
896214571Sdimstatic bfd_boolean
897214571Sdimmep_elf_object_p (bfd * abfd)
898214571Sdim{
899214571Sdim  /* Irix 5 and 6 is broken.  Object file symbol tables are not always
900214571Sdim     sorted correctly such that local symbols preceed global symbols,
901214571Sdim     and the sh_info field in the symbol table is not always right.  */
902214571Sdim  /* This is needed for the RELC support code.  */
903214571Sdim  elf_bad_symtab (abfd) = TRUE;
904214571Sdim  bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
905214571Sdim  return TRUE;
906214571Sdim}
907214571Sdim
908214571Sdimstatic bfd_boolean
909214571Sdimmep_elf_section_flags (flagword * flags, const Elf_Internal_Shdr * hdr)
910214571Sdim{
911214571Sdim  if (hdr->sh_flags & SHF_MEP_VLIW)
912214571Sdim    * flags |= SEC_MEP_VLIW;
913214571Sdim  return TRUE;
914214571Sdim}
915214571Sdim
916214571Sdimstatic bfd_boolean
917214571Sdimmep_elf_fake_sections (bfd *               abfd ATTRIBUTE_UNUSED,
918214571Sdim		       Elf_Internal_Shdr * hdr,
919214571Sdim		       asection *          sec)
920214571Sdim{
921214571Sdim  if (sec->flags & SEC_MEP_VLIW)
922214571Sdim    hdr->sh_flags |= SHF_MEP_VLIW;
923214571Sdim  return TRUE;
924214571Sdim}
925214571Sdim
926214571Sdim
927214571Sdim#define ELF_ARCH		bfd_arch_mep
928214571Sdim#define ELF_MACHINE_CODE	EM_CYGNUS_MEP
929214571Sdim#define ELF_MAXPAGESIZE		0x1000
930214571Sdim
931214571Sdim#define TARGET_BIG_SYM		bfd_elf32_mep_vec
932214571Sdim#define TARGET_BIG_NAME		"elf32-mep"
933214571Sdim
934214571Sdim#define TARGET_LITTLE_SYM	bfd_elf32_mep_little_vec
935214571Sdim#define TARGET_LITTLE_NAME	"elf32-mep-little"
936214571Sdim
937214571Sdim#define elf_info_to_howto_rel			NULL
938214571Sdim#define elf_info_to_howto			mep_info_to_howto_rela
939214571Sdim#define elf_backend_relocate_section		mep_elf_relocate_section
940214571Sdim#define elf_backend_gc_mark_hook		mep_elf_gc_mark_hook
941214571Sdim#define elf_backend_gc_sweep_hook		mep_elf_gc_sweep_hook
942214571Sdim#define elf_backend_check_relocs                mep_elf_check_relocs
943214571Sdim#define elf_backend_object_p		        mep_elf_object_p
944214571Sdim#define elf_backend_section_flags		mep_elf_section_flags
945214571Sdim#define elf_backend_fake_sections		mep_elf_fake_sections
946214571Sdim
947214571Sdim#define elf_backend_can_gc_sections		1
948214571Sdim
949214571Sdim#define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
950214571Sdim#define bfd_elf32_bfd_reloc_name_lookup	mep_reloc_name_lookup
951214571Sdim#define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
952214571Sdim#define bfd_elf32_bfd_copy_private_bfd_data	mep_elf_copy_private_bfd_data
953214571Sdim#define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
954214571Sdim#define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
955214571Sdim
956214571Sdim/* We use only the RELA entries.  */
957214571Sdim#define USE_RELA
958214571Sdim
959214571Sdim#include "elf32-target.h"
960