xref: /netbsd/external/gpl3/gdb/dist/bfd/aout-cris.c (revision 1424dfb3)
1377e23a2Schristos /* BFD backend for CRIS a.out binaries.
2*1424dfb3Schristos    Copyright (C) 2000-2020 Free Software Foundation, Inc.
3377e23a2Schristos    Contributed by Axis Communications AB.
4377e23a2Schristos    Written by Hans-Peter Nilsson.
5377e23a2Schristos 
6377e23a2Schristos    This file is part of BFD, the Binary File Descriptor library.
7377e23a2Schristos 
8377e23a2Schristos    This program is free software; you can redistribute it and/or modify
9377e23a2Schristos    it under the terms of the GNU General Public License as published by
10377e23a2Schristos    the Free Software Foundation; either version 3 of the License, or
11377e23a2Schristos    (at your option) any later version.
12377e23a2Schristos 
13377e23a2Schristos    This program is distributed in the hope that it will be useful,
14377e23a2Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
15377e23a2Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16377e23a2Schristos    GNU General Public License for more details.
17377e23a2Schristos 
18377e23a2Schristos    You should have received a copy of the GNU General Public License
19377e23a2Schristos    along with this program; if not, write to the Free Software
20377e23a2Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21377e23a2Schristos    MA 02110-1301, USA.  */
22377e23a2Schristos 
23377e23a2Schristos /* See info in the file PORTING for documentation of these macros and
24377e23a2Schristos    functions.  Beware; some of the information there is outdated.  */
25377e23a2Schristos 
26377e23a2Schristos #define N_HEADER_IN_TEXT(x) 0
27377e23a2Schristos #define N_TXTOFF(x)	    32
28377e23a2Schristos #define ENTRY_CAN_BE_ZERO
29377e23a2Schristos #define TEXT_START_ADDR     0
30377e23a2Schristos 
31377e23a2Schristos /* Without reading symbols to get the text start symbol, there is no way
32377e23a2Schristos    to know where the text segment starts in an a.out file.  Defaulting to
33377e23a2Schristos    anything as constant as TEXT_START_ADDR is bad.  But we can guess from
34377e23a2Schristos    the entry point, which is usually within the first 64k of the text
35377e23a2Schristos    segment.  We also assume here that the text segment is 64k-aligned.
36377e23a2Schristos    FIXME: It is also wrong to assume that data and bss follow immediately
37377e23a2Schristos    after text, but with those, we don't have any choice besides reading
38377e23a2Schristos    symbol info, and luckily there's no pressing need for correctness for
39377e23a2Schristos    those vma:s at this time.  */
40c03b94e9Schristos #define N_TXTADDR(x) ((x)->a_entry & ~(bfd_vma) 0xffff)
41377e23a2Schristos 
42377e23a2Schristos /* If you change this to 4, you can not link to an address N*4+2.  */
43377e23a2Schristos #define SEGMENT_SIZE 2
44377e23a2Schristos 
45377e23a2Schristos /* For some reason, if the a.out file has Z_MAGIC, then
46377e23a2Schristos    adata(abfd).exec_bytes_size is not used, but rather
47377e23a2Schristos    adata(abfd).zmagic_disk_block_size, even though the exec_header is
48377e23a2Schristos    *not* included in the text segment.  A simple workaround is to
49377e23a2Schristos    #define ZMAGIC_DISK_BLOCK_SIZE, which is used if defined; otherwise
50377e23a2Schristos    TARGET_PAGE_SIZE is used.  */
51377e23a2Schristos #define ZMAGIC_DISK_BLOCK_SIZE     N_TXTOFF (0)
52377e23a2Schristos 
53377e23a2Schristos /* It seems odd at first to set a page-size this low, but gives greater
54377e23a2Schristos    freedom in where things can be linked.  The drawback is that you have
55377e23a2Schristos    to set alignment and padding in linker scripts.  */
56377e23a2Schristos #define TARGET_PAGE_SIZE SEGMENT_SIZE
57377e23a2Schristos #define TARGETNAME "a.out-cris"
58377e23a2Schristos 
59377e23a2Schristos /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
60377e23a2Schristos    remove whitespace added here, and thus will fail to concatenate
61377e23a2Schristos    the tokens.  */
62377e23a2Schristos #define MY(OP) CONCAT2 (cris_aout_,OP)
63377e23a2Schristos #define NAME(x, y) CONCAT3 (cris_aout,_32_,y)
64377e23a2Schristos 
6548596154Schristos #include "sysdep.h"
66377e23a2Schristos #include "bfd.h"
67377e23a2Schristos 
68377e23a2Schristos /* Version 1 of the header.  */
69377e23a2Schristos #define MY_exec_hdr_flags 1
70377e23a2Schristos 
71377e23a2Schristos #define MY_write_object_contents MY (write_object_contents)
72377e23a2Schristos static bfd_boolean MY (write_object_contents) (bfd *);
73377e23a2Schristos 
74377e23a2Schristos /* Forward this, so we can use a pointer to it in PARAMS.  */
75377e23a2Schristos struct reloc_ext_external;
76377e23a2Schristos 
77377e23a2Schristos #define MY_swap_ext_reloc_out MY (swap_ext_reloc_out)
78377e23a2Schristos static void MY (swap_ext_reloc_out) (bfd *, arelent *, struct reloc_ext_external *);
79377e23a2Schristos 
80377e23a2Schristos #define MY_swap_ext_reloc_in MY (swap_ext_reloc_in)
81377e23a2Schristos static void MY (swap_ext_reloc_in) (bfd *, struct reloc_ext_external *,
82377e23a2Schristos 				    arelent *, asymbol **, bfd_size_type);
83377e23a2Schristos 
84377e23a2Schristos #define MY_set_sizes MY (set_sizes)
85377e23a2Schristos static bfd_boolean MY (set_sizes) (bfd *);
86377e23a2Schristos 
87377e23a2Schristos /* To set back reloc_size to ext, we make MY (set_sizes) be called
88377e23a2Schristos    through this construct.  Note that MY_set_arch_mach is only called
89377e23a2Schristos    through SET_ARCH_MACH.  The default bfd_default_set_arch_mach will
90377e23a2Schristos    not call set_sizes.  */
91377e23a2Schristos 
92c03b94e9Schristos #define SET_ARCH_MACH(BFD, EXECP) \
93*1424dfb3Schristos   bfd_set_arch_mach (BFD, bfd_arch_cris, N_MACHTYPE (EXECP))
94377e23a2Schristos 
95377e23a2Schristos /* These macros describe the binary layout of the reloc information we
96377e23a2Schristos    use in a file.  */
97377e23a2Schristos #define RELOC_EXT_BITS_EXTERN_LITTLE  0x80
98377e23a2Schristos #define RELOC_EXT_BITS_TYPE_LITTLE    3
99377e23a2Schristos #define RELOC_EXT_BITS_TYPE_SH_LITTLE 0
100377e23a2Schristos 
101377e23a2Schristos #ifndef MY_get_section_contents
102377e23a2Schristos #define MY_get_section_contents aout_32_get_section_contents
103377e23a2Schristos #endif
104377e23a2Schristos 
105377e23a2Schristos #define MACHTYPE_OK(mtype) ((mtype) == M_CRIS)
106377e23a2Schristos 
107377e23a2Schristos /* Include generic functions (some are overridden above).  */
108377e23a2Schristos #include "aout32.c"
109377e23a2Schristos #include "aout-target.h"
110377e23a2Schristos 
111377e23a2Schristos /* We need our own version to set header flags.  */
112377e23a2Schristos 
113377e23a2Schristos static bfd_boolean
MY(write_object_contents)114377e23a2Schristos MY (write_object_contents) (bfd *abfd)
115377e23a2Schristos {
116377e23a2Schristos   struct external_exec exec_bytes;
117377e23a2Schristos   struct internal_exec *execp = exec_hdr (abfd);
118377e23a2Schristos 
119377e23a2Schristos   /* We set the reloc type to RELOC_EXT_SIZE, although setting it at all
120377e23a2Schristos      seems unnecessary when inspecting as and ld behavior (not an
121377e23a2Schristos      exhaustive inspection).  The default write_object_contents
122377e23a2Schristos      definition sets RELOC_EXT_SIZE, so we follow suite and set it too.  */
123377e23a2Schristos   obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
124377e23a2Schristos 
125377e23a2Schristos   /* Setting N_SET_MACHTYPE and using N_SET_FLAGS is not performed by
126377e23a2Schristos      the default definition.  */
127377e23a2Schristos   if (bfd_get_arch (abfd) == bfd_arch_cris)
128c03b94e9Schristos     N_SET_MACHTYPE (execp, M_CRIS);
129377e23a2Schristos 
130c03b94e9Schristos   N_SET_FLAGS (execp, aout_backend_info (abfd)->exec_hdr_flags);
131377e23a2Schristos 
132377e23a2Schristos   WRITE_HEADERS (abfd, execp);
133377e23a2Schristos 
134377e23a2Schristos   return TRUE;
135377e23a2Schristos }
136377e23a2Schristos 
137377e23a2Schristos /* We need our own for these reasons:
138377e23a2Schristos    - Assert that a normal 8, 16 or 32 reloc is output.
139377e23a2Schristos    - Fix what seems to be a weak-bug (perhaps there for valid reasons).  */
140377e23a2Schristos 
141377e23a2Schristos static void
MY(swap_ext_reloc_out)142377e23a2Schristos MY (swap_ext_reloc_out) (bfd *abfd,
143377e23a2Schristos 			 arelent *g,
144377e23a2Schristos 			 struct reloc_ext_external *natptr)
145377e23a2Schristos {
146377e23a2Schristos   int r_index;
147377e23a2Schristos   int r_extern;
148377e23a2Schristos   unsigned int r_type;
149377e23a2Schristos   bfd_vma r_addend;
150377e23a2Schristos   asymbol *sym = *(g->sym_ptr_ptr);
151377e23a2Schristos   asection *output_section = sym->section->output_section;
152377e23a2Schristos 
153377e23a2Schristos   PUT_WORD (abfd, g->address, natptr->r_address);
154377e23a2Schristos 
155377e23a2Schristos   r_type = (unsigned int) g->howto->type;
156377e23a2Schristos 
157377e23a2Schristos   r_addend = g->addend;
158377e23a2Schristos   if ((sym->flags & BSF_SECTION_SYM) != 0)
159377e23a2Schristos     r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma;
160377e23a2Schristos 
161377e23a2Schristos   /* If this relocation is relative to a symbol then set the
162377e23a2Schristos      r_index to the symbols index, and the r_extern bit.
163377e23a2Schristos 
164377e23a2Schristos      Absolute symbols can come in in two ways, either as an offset
165377e23a2Schristos      from the abs section, or as a symbol which has an abs value.
166377e23a2Schristos      check for that here.  */
167377e23a2Schristos 
168*1424dfb3Schristos   if (bfd_is_abs_section (bfd_asymbol_section (sym)))
169377e23a2Schristos     {
170377e23a2Schristos       r_extern = 0;
171377e23a2Schristos       r_index = N_ABS;
172377e23a2Schristos     }
173377e23a2Schristos   else if ((sym->flags & BSF_SECTION_SYM) == 0)
174377e23a2Schristos     {
175*1424dfb3Schristos       if (bfd_is_und_section (bfd_asymbol_section (sym))
176377e23a2Schristos 	  /* Remember to check for weak symbols; they count as global.  */
177377e23a2Schristos 	  || (sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
178377e23a2Schristos 	r_extern = 1;
179377e23a2Schristos       else
180377e23a2Schristos 	r_extern = 0;
181377e23a2Schristos       r_index = (*(g->sym_ptr_ptr))->KEEPIT;
182377e23a2Schristos     }
183377e23a2Schristos   else
184377e23a2Schristos     {
185377e23a2Schristos       /* Just an ordinary section.  */
186377e23a2Schristos       r_extern = 0;
187377e23a2Schristos       r_index = output_section->target_index;
188377e23a2Schristos     }
189377e23a2Schristos 
190377e23a2Schristos   /* The relocation type is the same as the canonical ones, but only
191377e23a2Schristos      the first 3 are used: RELOC_8, RELOC_16, RELOC_32.
192377e23a2Schristos      We may change this later, but assert this for the moment.  */
193377e23a2Schristos   if (r_type > 2)
194377e23a2Schristos     {
1951c468f90Schristos       /* xgettext:c-format */
19607163879Schristos       _bfd_error_handler (_("%pB: unsupported relocation type exported: %#x"),
1971c468f90Schristos 			  abfd, r_type);
198377e23a2Schristos 
199377e23a2Schristos       bfd_set_error (bfd_error_wrong_format);
200377e23a2Schristos     }
201377e23a2Schristos 
202377e23a2Schristos   /* Now the fun stuff.  */
203377e23a2Schristos   natptr->r_index[2] = r_index >> 16;
204377e23a2Schristos   natptr->r_index[1] = r_index >> 8;
205377e23a2Schristos   natptr->r_index[0] = r_index;
206377e23a2Schristos   natptr->r_type[0] =
207377e23a2Schristos      (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
208377e23a2Schristos       | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
209377e23a2Schristos 
210377e23a2Schristos   PUT_WORD (abfd, r_addend, natptr->r_addend);
211377e23a2Schristos }
212377e23a2Schristos 
213377e23a2Schristos /* We need our own to assert that a normal 8, 16 or 32 reloc is input.  */
214377e23a2Schristos 
215377e23a2Schristos static void
MY(swap_ext_reloc_in)216377e23a2Schristos MY (swap_ext_reloc_in) (bfd *abfd,
217377e23a2Schristos 			struct reloc_ext_external *bytes,
218377e23a2Schristos 			arelent *cache_ptr,
219377e23a2Schristos 			asymbol **symbols,
220377e23a2Schristos 			bfd_size_type symcount)
221377e23a2Schristos {
222377e23a2Schristos   unsigned int r_index;
223377e23a2Schristos   int r_extern;
224377e23a2Schristos   unsigned int r_type;
225377e23a2Schristos   struct aoutdata *su = &(abfd->tdata.aout_data->a);
226377e23a2Schristos 
227377e23a2Schristos   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
228377e23a2Schristos 
229377e23a2Schristos   /* Now the fun stuff.  */
230*1424dfb3Schristos   r_index =  (((unsigned int) bytes->r_index[2] << 16)
231*1424dfb3Schristos     | ((unsigned int) bytes->r_index[1] << 8)
232*1424dfb3Schristos     |  bytes->r_index[0]);
233*1424dfb3Schristos 
234377e23a2Schristos   r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
235*1424dfb3Schristos 
236*1424dfb3Schristos   r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
237*1424dfb3Schristos     >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
238377e23a2Schristos 
239377e23a2Schristos   if (r_type > 2)
240377e23a2Schristos     {
2411c468f90Schristos       /* xgettext:c-format */
24207163879Schristos       _bfd_error_handler (_("%pB: unsupported relocation type imported: %#x"),
243377e23a2Schristos 			  abfd, r_type);
244377e23a2Schristos 
245377e23a2Schristos       bfd_set_error (bfd_error_wrong_format);
246377e23a2Schristos     }
247377e23a2Schristos 
248377e23a2Schristos   cache_ptr->howto =  howto_table_ext + r_type;
249377e23a2Schristos 
250377e23a2Schristos   if (r_extern && r_index > symcount)
251377e23a2Schristos     {
2521c468f90Schristos       _bfd_error_handler
2531c468f90Schristos 	/* xgettext:c-format */
25407163879Schristos 	(_("%pB: bad relocation record imported: %d"), abfd, r_index);
255377e23a2Schristos 
256377e23a2Schristos       bfd_set_error (bfd_error_wrong_format);
257377e23a2Schristos 
258377e23a2Schristos       /* We continue, so we can catch further errors.  */
259377e23a2Schristos       r_extern = 0;
260377e23a2Schristos       r_index = N_ABS;
261377e23a2Schristos     }
262377e23a2Schristos 
263377e23a2Schristos   /* Magically uses r_extern, symbols etc.  Ugly, but it's what's in the
264377e23a2Schristos      default.  */
265377e23a2Schristos   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
266377e23a2Schristos }
267377e23a2Schristos 
268377e23a2Schristos /* We use the same as the default, except that we also set
269377e23a2Schristos    "obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;", to avoid changing
270377e23a2Schristos    NAME (aout, set_arch_mach) in aoutx.  */
271377e23a2Schristos 
272377e23a2Schristos static bfd_boolean
MY(set_sizes)273377e23a2Schristos MY (set_sizes) (bfd *abfd)
274377e23a2Schristos {
275377e23a2Schristos   /* Just as the default in aout-target.h (with some #ifdefs folded)...  */
276377e23a2Schristos 
277377e23a2Schristos   adata (abfd).page_size = TARGET_PAGE_SIZE;
278377e23a2Schristos   adata (abfd).segment_size = SEGMENT_SIZE;
279377e23a2Schristos   adata (abfd).zmagic_disk_block_size = ZMAGIC_DISK_BLOCK_SIZE;
280377e23a2Schristos   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
281377e23a2Schristos 
282377e23a2Schristos   /* ... except for that we have the extended reloc.  The alternative
283377e23a2Schristos      would be to add a check on bfd_arch_cris in NAME (aout,
284377e23a2Schristos      set_arch_mach) in aoutx.h, but I don't want to do that since
285377e23a2Schristos      target-specific things should not be added there.  */
286377e23a2Schristos 
287377e23a2Schristos   obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
288377e23a2Schristos 
289377e23a2Schristos   return TRUE;
290377e23a2Schristos }
291