| 445 |
theseven |
1 |
/*
|
| 450 |
theseven |
2 |
* elf2emcoreapp.c: Convert ELF (or any BFD format) to emCORE executable format
|
|
|
3 |
*
|
|
|
4 |
* (c) 2011, Michael Sparmann <theseven@gmx.net>
|
|
|
5 |
*
|
|
|
6 |
* Based on:
|
| 445 |
theseven |
7 |
* elf2flt.c: Convert ELF (or any BFD format) to FLAT binary format
|
|
|
8 |
*
|
|
|
9 |
* (c) 1999-2002, Greg Ungerer <gerg@snapgear.com>
|
|
|
10 |
* Created elf2flt from coff2flt (see copyrights below). Added all the
|
|
|
11 |
* ELF format file handling. Extended relocation support for all of
|
|
|
12 |
* text and data.
|
|
|
13 |
*
|
|
|
14 |
* (c) 2006 Support the -a (use_resolved) option for TARGET_arm.
|
|
|
15 |
* Shaun Jackman <sjackman@gmail.com>
|
|
|
16 |
* (c) 2004, Nios II support, Wentao Xu <wentao@microtronix.com>
|
|
|
17 |
* (c) 2003, H8 support, ktrace <davidm@snapgear.com>
|
|
|
18 |
* (c) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>
|
|
|
19 |
* (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
|
|
|
20 |
* (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
|
|
|
21 |
* (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
|
|
|
22 |
* (c) 2001, zflat support <davidm@snapgear.com>
|
|
|
23 |
* (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and
|
|
|
24 |
* David McCullough <davidm@snapgear.com>
|
|
|
25 |
*
|
|
|
26 |
* Now supports PIC with GOT tables. This works by taking a '.elf' file
|
|
|
27 |
* and a fully linked elf executable (at address 0) and produces a flat
|
|
|
28 |
* file that can be loaded with some fixups. It still supports the old
|
|
|
29 |
* style fully relocatable elf format files.
|
|
|
30 |
*
|
|
|
31 |
* Originally obj-res.c
|
|
|
32 |
*
|
|
|
33 |
* (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
|
|
|
34 |
* (c) 1998, D. Jeff Dionne
|
|
|
35 |
* (c) 1998, The Silver Hammer Group Ltd.
|
|
|
36 |
* (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>
|
|
|
37 |
*
|
|
|
38 |
* This is Free Software, under the GNU Public Licence v2 or greater.
|
|
|
39 |
*
|
|
|
40 |
* Relocation added March 1997, Kresten Krab Thorup
|
|
|
41 |
* krab@california.daimi.aau.dk
|
|
|
42 |
*/
|
|
|
43 |
|
|
|
44 |
#include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
|
|
|
45 |
#include <stdlib.h> /* Userland prototypes of the ANSI C std lib functions */
|
|
|
46 |
#include <stdarg.h> /* Allows va_list to exist in the these namespaces */
|
|
|
47 |
#include <string.h> /* Userland prototypes of the string handling funcs */
|
|
|
48 |
#include <strings.h>
|
|
|
49 |
#include <unistd.h> /* Userland prototypes of the Unix std system calls */
|
|
|
50 |
#include <fcntl.h> /* Flag value for file handling functions */
|
|
|
51 |
#include <time.h>
|
|
|
52 |
|
|
|
53 |
/* from $(INSTALLDIR)/include */
|
|
|
54 |
#include <bfd.h> /* Main header file for the BFD library */
|
|
|
55 |
#include <libiberty.h>
|
|
|
56 |
|
|
|
57 |
#include "stubs.h"
|
|
|
58 |
const char *elf2flt_progname;
|
|
|
59 |
|
|
|
60 |
#if defined(TARGET_h8300)
|
|
|
61 |
#include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
|
|
|
62 |
#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(TARGET_nios) || defined(TARGET_nios2)
|
|
|
63 |
#include "cygwin-elf.h" /* Cygwin uses a local copy */
|
|
|
64 |
#elif defined(TARGET_microblaze)
|
|
|
65 |
#include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */
|
|
|
66 |
#else
|
|
|
67 |
#include <elf.h> /* TARGET_* ELF support for the BFD library */
|
|
|
68 |
#endif
|
|
|
69 |
|
|
|
70 |
/* Always include Blackfin-specific defines in addition to common ELF stuff
|
|
|
71 |
* above as the common elf headers often do not have our relocs.
|
|
|
72 |
*/
|
|
|
73 |
#if defined(TARGET_bfin) && !defined(R_BFIN_RIMM16)
|
|
|
74 |
#include "elf/bfin.h"
|
|
|
75 |
#endif
|
|
|
76 |
|
|
|
77 |
#if defined(__MINGW32__)
|
|
|
78 |
#include <getopt.h>
|
|
|
79 |
#endif
|
|
|
80 |
|
| 450 |
theseven |
81 |
#define _TOOL
|
|
|
82 |
#include "../../emcore/trunk/execimage.h"
|
| 445 |
theseven |
83 |
#include "compress.h"
|
|
|
84 |
|
|
|
85 |
#ifdef TARGET_e1
|
|
|
86 |
#include <e1.h>
|
|
|
87 |
#endif
|
|
|
88 |
|
|
|
89 |
#ifdef TARGET_v850e
|
|
|
90 |
#define TARGET_v850
|
|
|
91 |
#endif
|
|
|
92 |
|
|
|
93 |
#if defined(TARGET_m68k)
|
|
|
94 |
#define ARCH "m68k/coldfire"
|
|
|
95 |
#elif defined(TARGET_arm)
|
|
|
96 |
#define ARCH "arm"
|
|
|
97 |
#elif defined(TARGET_sparc)
|
|
|
98 |
#define ARCH "sparc"
|
|
|
99 |
#elif defined(TARGET_v850)
|
|
|
100 |
#define ARCH "v850"
|
|
|
101 |
#elif defined(TARGET_sh)
|
|
|
102 |
#define ARCH "sh"
|
|
|
103 |
#elif defined(TARGET_h8300)
|
|
|
104 |
#define ARCH "h8300"
|
|
|
105 |
#elif defined(TARGET_microblaze)
|
|
|
106 |
#define ARCH "microblaze"
|
|
|
107 |
#elif defined(TARGET_e1)
|
|
|
108 |
#define ARCH "e1-coff"
|
|
|
109 |
#elif defined(TARGET_bfin)
|
|
|
110 |
#define ARCH "bfin"
|
|
|
111 |
#elif defined(TARGET_nios)
|
|
|
112 |
#define ARCH "nios"
|
|
|
113 |
#elif defined(TARGET_nios2)
|
|
|
114 |
#define ARCH "nios2"
|
|
|
115 |
#else
|
|
|
116 |
#error "Don't know how to support your CPU architecture??"
|
|
|
117 |
#endif
|
|
|
118 |
|
| 450 |
theseven |
119 |
#ifndef R_ARM_V4BX
|
|
|
120 |
#define R_ARM_V4BX 40
|
|
|
121 |
#endif
|
|
|
122 |
#ifndef R_ARM_JUMP24
|
|
|
123 |
#define R_ARM_JUMP24 29
|
|
|
124 |
#endif
|
| 491 |
theseven |
125 |
#ifndef R_ARM_CALL
|
|
|
126 |
#define R_ARM_CALL 28
|
|
|
127 |
#endif
|
| 450 |
theseven |
128 |
|
| 445 |
theseven |
129 |
#if defined(TARGET_m68k) || defined(TARGET_h8300) || defined(TARGET_bfin)
|
|
|
130 |
/*
|
|
|
131 |
* Define a maximum number of bytes allowed in the offset table.
|
|
|
132 |
* We'll fail if the table is larger than this.
|
|
|
133 |
*
|
|
|
134 |
* This limit may be different for platforms other than m68k, but
|
|
|
135 |
* 8000 entries is a lot, trust me :-) (davidm)
|
|
|
136 |
*/
|
|
|
137 |
#define GOT_LIMIT 32767
|
|
|
138 |
/*
|
|
|
139 |
* we have to mask out the shared library id here and there, this gives
|
|
|
140 |
* us the real address bits when needed
|
|
|
141 |
*/
|
|
|
142 |
#define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
|
|
|
143 |
#else
|
|
|
144 |
#define real_address_bits(x) (x)
|
|
|
145 |
#endif
|
|
|
146 |
|
|
|
147 |
#ifndef O_BINARY
|
|
|
148 |
#define O_BINARY 0
|
|
|
149 |
#endif
|
|
|
150 |
|
|
|
151 |
|
|
|
152 |
int verbose = 0; /* extra output when running */
|
|
|
153 |
int pic_with_got = 0; /* do elf/got processing with PIC code */
|
| 466 |
theseven |
154 |
int load_to_ram = 1; /* instruct loader to allocate everything into RAM */
|
| 445 |
theseven |
155 |
int ktrace = 0; /* instruct loader output kernel trace on load */
|
| 466 |
theseven |
156 |
int docompress = 0; /* 1 = compress everything */
|
|
|
157 |
int lib = 0; /* 1 = this is a shared library */
|
| 445 |
theseven |
158 |
int use_resolved = 0; /* If true, get the value of symbol references from */
|
|
|
159 |
/* the program contents, not from the relocation table. */
|
|
|
160 |
/* In this case, the input ELF file must be already */
|
|
|
161 |
/* fully resolved (using the `-q' flag with recent */
|
|
|
162 |
/* versions of GNU ld will give you a fully resolved */
|
|
|
163 |
/* output file with relocation entries). */
|
|
|
164 |
|
|
|
165 |
/* Set if the text section contains any relocations. If it does, we must
|
|
|
166 |
set the load_to_ram flag. */
|
|
|
167 |
int text_has_relocs = 0;
|
|
|
168 |
|
|
|
169 |
asymbol**
|
|
|
170 |
get_symbols (bfd *abfd, long *num)
|
|
|
171 |
{
|
|
|
172 |
int32_t storage_needed;
|
|
|
173 |
asymbol **symbol_table;
|
|
|
174 |
long number_of_symbols;
|
|
|
175 |
|
|
|
176 |
storage_needed = bfd_get_symtab_upper_bound (abfd);
|
|
|
177 |
|
|
|
178 |
if (storage_needed < 0)
|
|
|
179 |
abort ();
|
|
|
180 |
|
|
|
181 |
if (storage_needed == 0)
|
|
|
182 |
return NULL;
|
|
|
183 |
|
|
|
184 |
symbol_table = xmalloc (storage_needed);
|
|
|
185 |
|
|
|
186 |
number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
|
|
|
187 |
|
|
|
188 |
if (number_of_symbols < 0)
|
|
|
189 |
abort ();
|
|
|
190 |
|
|
|
191 |
*num = number_of_symbols;
|
|
|
192 |
return symbol_table;
|
|
|
193 |
}
|
|
|
194 |
|
|
|
195 |
|
|
|
196 |
|
|
|
197 |
int
|
|
|
198 |
dump_symbols(asymbol **symbol_table, long number_of_symbols)
|
|
|
199 |
{
|
|
|
200 |
long i;
|
|
|
201 |
printf("SYMBOL TABLE:\n");
|
|
|
202 |
for (i=0; i<number_of_symbols; i++) {
|
|
|
203 |
printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
|
|
|
204 |
symbol_table[i]->value);
|
|
|
205 |
}
|
|
|
206 |
printf("\n");
|
|
|
207 |
return(0);
|
|
|
208 |
}
|
|
|
209 |
|
|
|
210 |
|
|
|
211 |
|
|
|
212 |
long
|
|
|
213 |
get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
|
|
|
214 |
{
|
|
|
215 |
long i;
|
|
|
216 |
for (i=0; i<number_of_symbols; i++) {
|
|
|
217 |
if (symbol_table[i]->section == sec) {
|
|
|
218 |
if (!strcmp(symbol_table[i]->name, name)) {
|
|
|
219 |
return symbol_table[i]->value;
|
|
|
220 |
}
|
|
|
221 |
}
|
|
|
222 |
}
|
|
|
223 |
return -1;
|
|
|
224 |
}
|
|
|
225 |
|
|
|
226 |
|
|
|
227 |
|
|
|
228 |
#ifdef TARGET_nios2
|
|
|
229 |
long
|
|
|
230 |
get_gp_value(asymbol **symbol_table, long number_of_symbols)
|
|
|
231 |
{
|
|
|
232 |
long i;
|
|
|
233 |
for (i=0; i<number_of_symbols; i++) {
|
|
|
234 |
if (!strcmp(symbol_table[i]->name, "_gp"))
|
|
|
235 |
return symbol_table[i]->value;
|
|
|
236 |
}
|
|
|
237 |
return -1;
|
|
|
238 |
}
|
|
|
239 |
#endif
|
|
|
240 |
|
|
|
241 |
|
|
|
242 |
|
|
|
243 |
int32_t
|
|
|
244 |
add_com_to_bss(asymbol **symbol_table, int32_t number_of_symbols, int32_t bss_len)
|
|
|
245 |
{
|
|
|
246 |
int32_t i, comsize;
|
|
|
247 |
int32_t offset;
|
|
|
248 |
|
|
|
249 |
comsize = 0;
|
|
|
250 |
for (i=0; i<number_of_symbols; i++) {
|
|
|
251 |
if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
|
|
|
252 |
offset = bss_len + comsize;
|
|
|
253 |
comsize += symbol_table[i]->value;
|
|
|
254 |
symbol_table[i]->value = offset;
|
|
|
255 |
}
|
|
|
256 |
}
|
|
|
257 |
return comsize;
|
|
|
258 |
}
|
|
|
259 |
|
|
|
260 |
#ifdef TARGET_bfin
|
|
|
261 |
/* FUNCTION : weak_und_symbol
|
|
|
262 |
ABSTRACT : return true if symbol is weak and undefined.
|
|
|
263 |
*/
|
|
|
264 |
static int
|
|
|
265 |
weak_und_symbol(const char *reloc_section_name,
|
|
|
266 |
struct bfd_symbol *symbol)
|
|
|
267 |
{
|
|
|
268 |
if (!(strstr (reloc_section_name, "text")
|
|
|
269 |
|| strstr (reloc_section_name, "data")
|
|
|
270 |
|| strstr (reloc_section_name, "bss"))) {
|
|
|
271 |
if (symbol->flags & BSF_WEAK) {
|
|
|
272 |
#ifdef DEBUG_BFIN
|
|
|
273 |
fprintf(stderr, "found weak undefined symbol %s\n", symbol->name);
|
|
|
274 |
#endif
|
|
|
275 |
return TRUE;
|
|
|
276 |
}
|
|
|
277 |
}
|
|
|
278 |
return FALSE;
|
|
|
279 |
}
|
|
|
280 |
|
|
|
281 |
static int
|
|
|
282 |
bfin_set_reloc (uint32_t *reloc,
|
|
|
283 |
const char *reloc_section_name,
|
|
|
284 |
const char *sym_name,
|
|
|
285 |
struct bfd_symbol *symbol,
|
|
|
286 |
int sp, int32_t offset)
|
|
|
287 |
{
|
|
|
288 |
unsigned int type = 0;
|
|
|
289 |
uint32_t val;
|
|
|
290 |
|
|
|
291 |
if (strstr (reloc_section_name, "stack")) {
|
|
|
292 |
if (verbose)
|
|
|
293 |
printf ("Stack-relative reloc, offset %08lx\n", offset);
|
|
|
294 |
/* This must be a stack_start reloc for stack checking. */
|
|
|
295 |
type = 1;
|
|
|
296 |
}
|
|
|
297 |
val = (offset & ((1 << 26) - 1));
|
|
|
298 |
val |= (sp & (1 << 3) - 1) << 26;
|
|
|
299 |
val |= type << 29;
|
|
|
300 |
*reloc = val;
|
|
|
301 |
return 0;
|
|
|
302 |
}
|
|
|
303 |
|
|
|
304 |
static bfd *compare_relocs_bfd;
|
|
|
305 |
|
|
|
306 |
static int
|
|
|
307 |
compare_relocs (const void *pa, const void *pb)
|
|
|
308 |
{
|
|
|
309 |
const arelent *const *a = pa, *const *b = pb;
|
|
|
310 |
const arelent *ra = *a, *rb = *b;
|
|
|
311 |
unsigned long va, vb;
|
|
|
312 |
uint32_t a_vma, b_vma;
|
|
|
313 |
|
|
|
314 |
if (!ra->sym_ptr_ptr || !*ra->sym_ptr_ptr)
|
|
|
315 |
return -1;
|
|
|
316 |
else if (!rb->sym_ptr_ptr || !*rb->sym_ptr_ptr)
|
|
|
317 |
return 1;
|
|
|
318 |
|
|
|
319 |
a_vma = bfd_section_vma(compare_relocs_bfd,
|
|
|
320 |
(*(ra->sym_ptr_ptr))->section);
|
|
|
321 |
b_vma = bfd_section_vma(compare_relocs_bfd,
|
|
|
322 |
(*(rb->sym_ptr_ptr))->section);
|
|
|
323 |
va = (*(ra->sym_ptr_ptr))->value + a_vma + ra->addend;
|
|
|
324 |
vb = (*(rb->sym_ptr_ptr))->value + b_vma + rb->addend;
|
|
|
325 |
return va - vb;
|
|
|
326 |
}
|
|
|
327 |
#endif
|
|
|
328 |
|
|
|
329 |
uint32_t *
|
|
|
330 |
output_relocs (
|
|
|
331 |
bfd *abs_bfd,
|
|
|
332 |
asymbol **symbols,
|
|
|
333 |
int number_of_symbols,
|
|
|
334 |
uint32_t *n_relocs,
|
|
|
335 |
unsigned char *text, int text_len, uint32_t text_vma,
|
|
|
336 |
unsigned char *data, int data_len, uint32_t data_vma,
|
|
|
337 |
bfd *rel_bfd)
|
|
|
338 |
{
|
|
|
339 |
uint32_t *flat_relocs;
|
|
|
340 |
asection *a, *sym_section, *r;
|
|
|
341 |
arelent **relpp, **p, *q;
|
|
|
342 |
const char *sym_name, *section_name;
|
|
|
343 |
unsigned char *sectionp;
|
|
|
344 |
unsigned long pflags;
|
|
|
345 |
char addstr[16];
|
|
|
346 |
uint32_t sym_addr, sym_vma, section_vma;
|
|
|
347 |
int relsize, relcount;
|
|
|
348 |
int flat_reloc_count;
|
|
|
349 |
int sym_reloc_size, rc;
|
|
|
350 |
int got_size = 0;
|
|
|
351 |
int bad_relocs = 0;
|
|
|
352 |
asymbol **symb;
|
|
|
353 |
long nsymb;
|
|
|
354 |
#ifdef TARGET_bfin
|
|
|
355 |
unsigned long persistent_data = 0;
|
|
|
356 |
#endif
|
|
|
357 |
|
|
|
358 |
#if 0
|
|
|
359 |
printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
|
|
|
360 |
"n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
|
|
|
361 |
__FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
|
|
|
362 |
text, text_len, data, data_len);
|
|
|
363 |
#endif
|
|
|
364 |
|
|
|
365 |
#if 0
|
|
|
366 |
dump_symbols(symbols, number_of_symbols);
|
|
|
367 |
#endif
|
|
|
368 |
|
|
|
369 |
*n_relocs = 0;
|
|
|
370 |
flat_relocs = NULL;
|
|
|
371 |
flat_reloc_count = 0;
|
|
|
372 |
rc = 0;
|
|
|
373 |
pflags = 0;
|
|
|
374 |
|
|
|
375 |
/* Determine how big our offset table is in bytes.
|
|
|
376 |
* This isn't too difficult as we've terminated the table with -1.
|
|
|
377 |
* Also note that both the relocatable and absolute versions have this
|
|
|
378 |
* terminator even though the relocatable one doesn't have the GOT!
|
|
|
379 |
*/
|
|
|
380 |
if (pic_with_got && !use_resolved) {
|
|
|
381 |
uint32_t *lp = (uint32_t *)data;
|
|
|
382 |
/* Should call ntohl(*lp) here but is isn't going to matter */
|
|
|
383 |
while (*lp != 0xffffffff) lp++;
|
|
|
384 |
got_size = ((unsigned char *)lp) - data;
|
|
|
385 |
if (verbose)
|
|
|
386 |
printf("GOT table contains %d entries (%d bytes)\n",
|
|
|
387 |
got_size/sizeof(uint32_t), got_size);
|
|
|
388 |
#ifdef TARGET_m68k
|
|
|
389 |
if (got_size > GOT_LIMIT)
|
|
|
390 |
fatal("GOT too large: %d bytes (limit = %d bytes)",
|
|
|
391 |
got_size, GOT_LIMIT);
|
|
|
392 |
#endif
|
|
|
393 |
}
|
|
|
394 |
|
|
|
395 |
for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
|
|
|
396 |
section_vma = bfd_section_vma(abs_bfd, a);
|
|
|
397 |
|
|
|
398 |
if (verbose)
|
|
|
399 |
printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
|
|
|
400 |
a->flags, section_vma);
|
|
|
401 |
|
|
|
402 |
// if (bfd_is_abs_section(a))
|
|
|
403 |
// continue;
|
|
|
404 |
if (bfd_is_und_section(a))
|
|
|
405 |
continue;
|
|
|
406 |
if (bfd_is_com_section(a))
|
|
|
407 |
continue;
|
|
|
408 |
// if ((a->flags & SEC_RELOC) == 0)
|
|
|
409 |
// continue;
|
|
|
410 |
|
|
|
411 |
/*
|
|
|
412 |
* Only relocate things in the data sections if we are PIC/GOT.
|
|
|
413 |
* otherwise do text as well
|
|
|
414 |
*/
|
|
|
415 |
if ((!pic_with_got || ALWAYS_RELOC_TEXT) && (a->flags & SEC_CODE))
|
|
|
416 |
sectionp = text + (a->vma - text_vma);
|
|
|
417 |
else if (a->flags & SEC_DATA)
|
|
|
418 |
sectionp = data + (a->vma - data_vma);
|
|
|
419 |
else
|
|
|
420 |
continue;
|
|
|
421 |
|
|
|
422 |
/* Now search for the equivalent section in the relocation binary
|
|
|
423 |
* and use that relocation information to build reloc entries
|
|
|
424 |
* for this one.
|
|
|
425 |
*/
|
|
|
426 |
for (r=rel_bfd->sections; r != NULL; r=r->next)
|
|
|
427 |
if (strcmp(a->name, r->name) == 0)
|
|
|
428 |
break;
|
|
|
429 |
if (r == NULL)
|
|
|
430 |
continue;
|
|
|
431 |
if (verbose)
|
|
|
432 |
printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
|
|
|
433 |
r->flags, bfd_section_vma(abs_bfd, r));
|
|
|
434 |
if ((r->flags & SEC_RELOC) == 0)
|
|
|
435 |
continue;
|
|
|
436 |
relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
|
|
|
437 |
if (relsize <= 0) {
|
|
|
438 |
if (verbose)
|
|
|
439 |
printf("%s(%d): no relocation entries section=0x%x\n",
|
|
|
440 |
__FILE__, __LINE__, r->name);
|
|
|
441 |
continue;
|
|
|
442 |
}
|
|
|
443 |
|
|
|
444 |
symb = get_symbols(rel_bfd, &nsymb);
|
|
|
445 |
relpp = xmalloc(relsize);
|
|
|
446 |
|
|
|
447 |
relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
|
|
|
448 |
if (relcount <= 0) {
|
|
|
449 |
if (verbose)
|
|
|
450 |
printf("%s(%d): no relocation entries section=%s\n",
|
|
|
451 |
__FILE__, __LINE__, r->name);
|
|
|
452 |
continue;
|
|
|
453 |
} else {
|
|
|
454 |
#ifdef TARGET_bfin
|
|
|
455 |
compare_relocs_bfd = abs_bfd;
|
|
|
456 |
qsort (relpp, relcount, sizeof *relpp, compare_relocs);
|
|
|
457 |
#endif
|
|
|
458 |
for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
|
|
|
459 |
unsigned char *r_mem;
|
|
|
460 |
int relocation_needed = 0;
|
|
|
461 |
|
|
|
462 |
#ifdef TARGET_microblaze
|
|
|
463 |
/* The MICROBLAZE_XX_NONE relocs can be skipped.
|
|
|
464 |
They represent PC relative branches that the
|
|
|
465 |
linker has already resolved */
|
|
|
466 |
|
|
|
467 |
switch ((*p)->howto->type)
|
|
|
468 |
{
|
|
|
469 |
case R_MICROBLAZE_NONE:
|
|
|
470 |
case R_MICROBLAZE_64_NONE:
|
|
|
471 |
case R_MICROBLAZE_32_PCREL_LO:
|
|
|
472 |
continue;
|
|
|
473 |
}
|
|
|
474 |
#endif /* TARGET_microblaze */
|
|
|
475 |
|
|
|
476 |
#ifdef TARGET_v850
|
|
|
477 |
/* Skip this relocation entirely if possible (we
|
|
|
478 |
do this early, before doing any other
|
|
|
479 |
processing on it). */
|
|
|
480 |
switch ((*p)->howto->type) {
|
|
|
481 |
#ifdef R_V850_9_PCREL
|
|
|
482 |
case R_V850_9_PCREL:
|
|
|
483 |
#endif
|
|
|
484 |
#ifdef R_V850_22_PCREL
|
|
|
485 |
case R_V850_22_PCREL:
|
|
|
486 |
#endif
|
|
|
487 |
#ifdef R_V850_SDA_16_16_OFFSET
|
|
|
488 |
case R_V850_SDA_16_16_OFFSET:
|
|
|
489 |
#endif
|
|
|
490 |
#ifdef R_V850_SDA_15_16_OFFSET
|
|
|
491 |
case R_V850_SDA_15_16_OFFSET:
|
|
|
492 |
#endif
|
|
|
493 |
#ifdef R_V850_ZDA_15_16_OFFSET
|
|
|
494 |
case R_V850_ZDA_15_16_OFFSET:
|
|
|
495 |
#endif
|
|
|
496 |
#ifdef R_V850_TDA_6_8_OFFSET
|
|
|
497 |
case R_V850_TDA_6_8_OFFSET:
|
|
|
498 |
#endif
|
|
|
499 |
#ifdef R_V850_TDA_7_8_OFFSET
|
|
|
500 |
case R_V850_TDA_7_8_OFFSET:
|
|
|
501 |
#endif
|
|
|
502 |
#ifdef R_V850_TDA_7_7_OFFSET
|
|
|
503 |
case R_V850_TDA_7_7_OFFSET:
|
|
|
504 |
#endif
|
|
|
505 |
#ifdef R_V850_TDA_16_16_OFFSET
|
|
|
506 |
case R_V850_TDA_16_16_OFFSET:
|
|
|
507 |
#endif
|
|
|
508 |
#ifdef R_V850_TDA_4_5_OFFSET
|
|
|
509 |
case R_V850_TDA_4_5_OFFSET:
|
|
|
510 |
#endif
|
|
|
511 |
#ifdef R_V850_TDA_4_4_OFFSET
|
|
|
512 |
case R_V850_TDA_4_4_OFFSET:
|
|
|
513 |
#endif
|
|
|
514 |
#ifdef R_V850_SDA_16_16_SPLIT_OFFSET
|
|
|
515 |
case R_V850_SDA_16_16_SPLIT_OFFSET:
|
|
|
516 |
#endif
|
|
|
517 |
#ifdef R_V850_CALLT_6_7_OFFSET
|
|
|
518 |
case R_V850_CALLT_6_7_OFFSET:
|
|
|
519 |
#endif
|
|
|
520 |
#ifdef R_V850_CALLT_16_16_OFFSET
|
|
|
521 |
case R_V850_CALLT_16_16_OFFSET:
|
|
|
522 |
#endif
|
|
|
523 |
/* These are relative relocations, which
|
|
|
524 |
have already been fixed up by the
|
|
|
525 |
linker at this point, so just ignore
|
|
|
526 |
them. */
|
|
|
527 |
continue;
|
|
|
528 |
}
|
|
|
529 |
#endif /* USE_V850_RELOCS */
|
|
|
530 |
|
|
|
531 |
q = *p;
|
|
|
532 |
if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
|
|
|
533 |
sym_name = (*(q->sym_ptr_ptr))->name;
|
|
|
534 |
sym_section = (*(q->sym_ptr_ptr))->section;
|
|
|
535 |
section_name=(*(q->sym_ptr_ptr))->section->name;
|
|
|
536 |
} else {
|
|
|
537 |
printf("ERROR: undefined relocation entry\n");
|
|
|
538 |
rc = -1;
|
|
|
539 |
continue;
|
|
|
540 |
}
|
|
|
541 |
#ifndef TARGET_bfin
|
|
|
542 |
/* Adjust the address to account for the GOT table which wasn't
|
|
|
543 |
* present in the relative file link.
|
|
|
544 |
*/
|
|
|
545 |
if (pic_with_got && !use_resolved)
|
|
|
546 |
q->address += got_size;
|
|
|
547 |
#endif
|
|
|
548 |
|
|
|
549 |
/* A pointer to what's being relocated, used often
|
|
|
550 |
below. */
|
|
|
551 |
r_mem = sectionp + q->address;
|
|
|
552 |
|
|
|
553 |
/*
|
|
|
554 |
* Fixup offset in the actual section.
|
|
|
555 |
*/
|
|
|
556 |
addstr[0] = 0;
|
|
|
557 |
#if !defined TARGET_e1 && !defined TARGET_bfin
|
|
|
558 |
if ((sym_addr = get_symbol_offset((char *) sym_name,
|
|
|
559 |
sym_section, symbols, number_of_symbols)) == -1) {
|
|
|
560 |
sym_addr = 0;
|
|
|
561 |
}
|
|
|
562 |
#else
|
|
|
563 |
sym_addr = (*(q->sym_ptr_ptr))->value;
|
|
|
564 |
#endif
|
|
|
565 |
if (use_resolved) {
|
|
|
566 |
/* Use the address of the symbol already in
|
|
|
567 |
the program text. How this is handled may
|
|
|
568 |
still depend on the particular relocation
|
|
|
569 |
though. */
|
|
|
570 |
switch (q->howto->type) {
|
|
|
571 |
int r2_type;
|
|
|
572 |
#ifdef TARGET_v850
|
|
|
573 |
case R_V850_HI16_S:
|
|
|
574 |
/* We specially handle adjacent
|
|
|
575 |
HI16_S/ZDA_15_16_OFFSET and
|
|
|
576 |
HI16_S/LO16 pairs that reference the
|
|
|
577 |
same address (these are usually
|
|
|
578 |
movhi/ld and movhi/movea pairs,
|
|
|
579 |
respectively). */
|
|
|
580 |
if (relcount == 0)
|
|
|
581 |
r2_type = R_V850_NONE;
|
|
|
582 |
else
|
|
|
583 |
r2_type = p[1]->howto->type;
|
|
|
584 |
if ((r2_type == R_V850_ZDA_15_16_OFFSET
|
|
|
585 |
|| r2_type == R_V850_LO16)
|
|
|
586 |
&& (p[0]->sym_ptr_ptr
|
|
|
587 |
== p[1]->sym_ptr_ptr)
|
|
|
588 |
&& (p[0]->addend == p[1]->addend))
|
|
|
589 |
{
|
|
|
590 |
relocation_needed = 1;
|
|
|
591 |
|
|
|
592 |
switch (r2_type) {
|
|
|
593 |
case R_V850_ZDA_15_16_OFFSET:
|
|
|
594 |
pflags = 0x10000000;
|
|
|
595 |
break;
|
|
|
596 |
case R_V850_LO16:
|
|
|
597 |
pflags = 0x20000000;
|
|
|
598 |
break;
|
|
|
599 |
}
|
|
|
600 |
|
|
|
601 |
/* We don't really need the
|
|
|
602 |
actual value -- the bits
|
|
|
603 |
produced by the linker are
|
|
|
604 |
what we want in the final
|
|
|
605 |
flat file -- but get it
|
|
|
606 |
anyway if useful for
|
|
|
607 |
debugging. */
|
|
|
608 |
if (verbose) {
|
|
|
609 |
unsigned char *r2_mem =
|
|
|
610 |
sectionp
|
|
|
611 |
+ p[1]->address;
|
|
|
612 |
/* little-endian */
|
|
|
613 |
int hi = r_mem[0]
|
|
|
614 |
+ (r_mem[1] << 8);
|
|
|
615 |
int lo = r2_mem[0]
|
|
|
616 |
+ (r2_mem[1] << 8);
|
|
|
617 |
/* Sign extend LO. */
|
|
|
618 |
lo = (lo ^ 0x8000)
|
|
|
619 |
- 0x8000;
|
|
|
620 |
|
|
|
621 |
/* Maybe ignore the LSB
|
|
|
622 |
of LO, which is
|
|
|
623 |
actually part of the
|
|
|
624 |
instruction. */
|
|
|
625 |
if (r2_type != R_V850_LO16)
|
|
|
626 |
lo &= ~1;
|
|
|
627 |
|
|
|
628 |
sym_addr =
|
|
|
629 |
(hi << 16)
|
|
|
630 |
+ lo;
|
|
|
631 |
}
|
|
|
632 |
} else
|
|
|
633 |
goto bad_resolved_reloc;
|
|
|
634 |
break;
|
|
|
635 |
|
|
|
636 |
case R_V850_LO16:
|
|
|
637 |
/* See if this is actually the
|
|
|
638 |
2nd half of a pair. */
|
|
|
639 |
if (p > relpp
|
|
|
640 |
&& (p[-1]->howto->type
|
|
|
641 |
== R_V850_HI16_S)
|
|
|
642 |
&& (p[-1]->sym_ptr_ptr
|
|
|
643 |
== p[0]->sym_ptr_ptr)
|
|
|
644 |
&& (p[-1]->addend == p[0]->addend))
|
|
|
645 |
break; /* not an error */
|
|
|
646 |
else
|
|
|
647 |
goto bad_resolved_reloc;
|
|
|
648 |
|
|
|
649 |
case R_V850_HI16:
|
|
|
650 |
goto bad_resolved_reloc;
|
|
|
651 |
default:
|
|
|
652 |
goto good_32bit_resolved_reloc;
|
|
|
653 |
#elif defined(TARGET_arm)
|
|
|
654 |
case R_ARM_ABS32:
|
|
|
655 |
relocation_needed = 1;
|
|
|
656 |
break;
|
|
|
657 |
case R_ARM_REL32:
|
|
|
658 |
case R_ARM_THM_PC11:
|
|
|
659 |
case R_ARM_THM_PC22:
|
|
|
660 |
case R_ARM_PC24:
|
|
|
661 |
case R_ARM_PLT32:
|
|
|
662 |
case R_ARM_GOTPC:
|
|
|
663 |
case R_ARM_GOT32:
|
| 447 |
theseven |
664 |
case R_ARM_V4BX:
|
| 445 |
theseven |
665 |
relocation_needed = 0;
|
|
|
666 |
break;
|
|
|
667 |
default:
|
|
|
668 |
goto bad_resolved_reloc;
|
|
|
669 |
#elif defined(TARGET_m68k)
|
|
|
670 |
case R_68K_32:
|
|
|
671 |
goto good_32bit_resolved_reloc;
|
|
|
672 |
case R_68K_PC32:
|
|
|
673 |
case R_68K_PC16:
|
|
|
674 |
/* The linker has already resolved
|
|
|
675 |
PC relocs for us. In PIC links,
|
|
|
676 |
the symbol must be in the data
|
|
|
677 |
segment. */
|
|
|
678 |
case R_68K_NONE:
|
|
|
679 |
continue;
|
|
|
680 |
default:
|
|
|
681 |
goto bad_resolved_reloc;
|
|
|
682 |
#elif defined TARGET_bfin
|
|
|
683 |
case R_BFIN_RIMM16:
|
|
|
684 |
case R_BFIN_LUIMM16:
|
|
|
685 |
case R_BFIN_HUIMM16:
|
|
|
686 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
687 |
sym_addr += sym_vma + q->addend;
|
|
|
688 |
|
|
|
689 |
if (weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr))))
|
|
|
690 |
continue;
|
|
|
691 |
if (q->howto->type == R_BFIN_RIMM16 && (0xFFFF0000 & sym_addr)) {
|
|
|
692 |
fprintf (stderr, "Relocation overflow for rN = %s\n",sym_name);
|
|
|
693 |
bad_relocs++;
|
|
|
694 |
}
|
|
|
695 |
if ((0xFFFF0000 & sym_addr) != persistent_data) {
|
|
|
696 |
flat_relocs = (uint32_t *)
|
|
|
697 |
(realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
|
|
|
698 |
if (verbose)
|
|
|
699 |
printf ("New persistent data for %08lx\n", sym_addr);
|
|
|
700 |
persistent_data = 0xFFFF0000 & sym_addr;
|
|
|
701 |
flat_relocs[flat_reloc_count++]
|
|
|
702 |
= (sym_addr >> 16) | (3 << 26);
|
|
|
703 |
}
|
|
|
704 |
|
|
|
705 |
flat_relocs = (uint32_t *)
|
|
|
706 |
(realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
|
|
|
707 |
if (bfin_set_reloc (flat_relocs + flat_reloc_count,
|
|
|
708 |
sym_section->name, sym_name,
|
|
|
709 |
(*(q->sym_ptr_ptr)),
|
|
|
710 |
q->howto->type == R_BFIN_HUIMM16 ? 1 : 0,
|
|
|
711 |
section_vma + q->address))
|
|
|
712 |
bad_relocs++;
|
|
|
713 |
if (a->flags & SEC_CODE)
|
|
|
714 |
text_has_relocs = 1;
|
|
|
715 |
flat_reloc_count++;
|
|
|
716 |
break;
|
|
|
717 |
|
|
|
718 |
case R_BFIN_BYTE4_DATA:
|
|
|
719 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
720 |
sym_addr += sym_vma + q->addend;
|
|
|
721 |
|
|
|
722 |
if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr))))
|
|
|
723 |
continue;
|
|
|
724 |
|
|
|
725 |
flat_relocs = (uint32_t *)
|
|
|
726 |
(realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
|
|
|
727 |
if (bfin_set_reloc (flat_relocs + flat_reloc_count,
|
|
|
728 |
sym_section->name, sym_name,
|
|
|
729 |
(*(q->sym_ptr_ptr)),
|
|
|
730 |
2, section_vma + q->address))
|
|
|
731 |
bad_relocs++;
|
|
|
732 |
if (a->flags & SEC_CODE)
|
|
|
733 |
text_has_relocs = 1;
|
|
|
734 |
|
|
|
735 |
flat_reloc_count++;
|
|
|
736 |
break;
|
|
|
737 |
#else
|
|
|
738 |
default:
|
|
|
739 |
/* The default is to assume that the
|
|
|
740 |
relocation is relative and has
|
|
|
741 |
already been fixed up by the
|
|
|
742 |
linker (perhaps we ought to make
|
|
|
743 |
give an error by default, and
|
|
|
744 |
require `safe' relocations to be
|
|
|
745 |
enumberated explicitly?). */
|
|
|
746 |
goto good_32bit_resolved_reloc;
|
|
|
747 |
#endif
|
|
|
748 |
good_32bit_resolved_reloc:
|
|
|
749 |
if (bfd_big_endian (abs_bfd))
|
|
|
750 |
sym_addr =
|
|
|
751 |
(r_mem[0] << 24)
|
|
|
752 |
+ (r_mem[1] << 16)
|
|
|
753 |
+ (r_mem[2] << 8)
|
|
|
754 |
+ r_mem[3];
|
|
|
755 |
else
|
|
|
756 |
sym_addr =
|
|
|
757 |
r_mem[0]
|
|
|
758 |
+ (r_mem[1] << 8)
|
|
|
759 |
+ (r_mem[2] << 16)
|
|
|
760 |
+ (r_mem[3] << 24);
|
|
|
761 |
relocation_needed = 1;
|
|
|
762 |
break;
|
|
|
763 |
|
|
|
764 |
bad_resolved_reloc:
|
|
|
765 |
printf("ERROR: reloc type %s unsupported in this context\n",
|
|
|
766 |
q->howto->name);
|
|
|
767 |
bad_relocs++;
|
|
|
768 |
break;
|
|
|
769 |
}
|
|
|
770 |
} else {
|
|
|
771 |
/* Calculate the sym address ourselves. */
|
|
|
772 |
sym_reloc_size = bfd_get_reloc_size(q->howto);
|
|
|
773 |
|
|
|
774 |
#if !defined(TARGET_h8300) && !defined(TARGET_e1) && !defined(TARGET_bfin) && !defined(TARGET_m68k)
|
| 871 |
theseven |
775 |
if ((*p)->howto->type && sym_reloc_size != 4) {
|
| 445 |
theseven |
776 |
printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
|
|
|
777 |
(*p)->howto->type, sym_reloc_size, sym_name);
|
|
|
778 |
bad_relocs++;
|
|
|
779 |
rc = -1;
|
|
|
780 |
continue;
|
|
|
781 |
}
|
|
|
782 |
#endif
|
|
|
783 |
|
|
|
784 |
switch ((*p)->howto->type) {
|
|
|
785 |
|
|
|
786 |
#if defined(TARGET_m68k)
|
|
|
787 |
case R_68K_32:
|
|
|
788 |
relocation_needed = 1;
|
|
|
789 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
790 |
sym_addr += sym_vma + q->addend;
|
|
|
791 |
break;
|
|
|
792 |
case R_68K_PC16:
|
|
|
793 |
case R_68K_PC32:
|
|
|
794 |
sym_vma = 0;
|
|
|
795 |
sym_addr += sym_vma + q->addend;
|
|
|
796 |
sym_addr -= q->address;
|
|
|
797 |
break;
|
|
|
798 |
#endif
|
|
|
799 |
|
|
|
800 |
#if defined(TARGET_arm)
|
| 872 |
theseven |
801 |
case 0:
|
|
|
802 |
if (!sym_section->flags) break;
|
| 445 |
theseven |
803 |
case R_ARM_ABS32:
|
|
|
804 |
relocation_needed = 1;
|
| 450 |
theseven |
805 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
806 |
sym_addr += sym_vma + q->addend;
|
| 445 |
theseven |
807 |
if (verbose)
|
|
|
808 |
fprintf(stderr,
|
|
|
809 |
"%s vma=0x%x, value=0x%x, address=0x%x "
|
|
|
810 |
"sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
|
|
|
811 |
"ABS32",
|
|
|
812 |
sym_vma, (*(q->sym_ptr_ptr))->value,
|
|
|
813 |
q->address, sym_addr,
|
|
|
814 |
(*p)->howto->rightshift,
|
|
|
815 |
*(uint32_t *)r_mem);
|
|
|
816 |
break;
|
|
|
817 |
case R_ARM_GOT32:
|
|
|
818 |
case R_ARM_GOTPC:
|
| 449 |
theseven |
819 |
case R_ARM_V4BX:
|
| 445 |
theseven |
820 |
/* Should be fine as is */
|
|
|
821 |
break;
|
|
|
822 |
case R_ARM_PLT32:
|
|
|
823 |
if (verbose)
|
|
|
824 |
fprintf(stderr,
|
|
|
825 |
"%s vma=0x%x, value=0x%x, address=0x%x "
|
|
|
826 |
"sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
|
|
|
827 |
"PLT32",
|
| 450 |
theseven |
828 |
0, (*(q->sym_ptr_ptr))->value,
|
|
|
829 |
q->address, (sym_addr-q->address)>>(*p)->howto->rightshift,
|
| 445 |
theseven |
830 |
(*p)->howto->rightshift,
|
|
|
831 |
*(uint32_t *)r_mem);
|
|
|
832 |
case R_ARM_PC24:
|
| 449 |
theseven |
833 |
case R_ARM_JUMP24:
|
| 491 |
theseven |
834 |
case R_ARM_CALL:
|
| 445 |
theseven |
835 |
sym_vma = 0;
|
|
|
836 |
sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
|
|
|
837 |
break;
|
|
|
838 |
#endif
|
|
|
839 |
|
|
|
840 |
#ifdef TARGET_v850
|
|
|
841 |
case R_V850_32:
|
|
|
842 |
relocation_needed = 1;
|
|
|
843 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
844 |
sym_addr += sym_vma + q->addend;
|
|
|
845 |
break;
|
|
|
846 |
#if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
|
|
|
847 |
#ifdef R_V850_ZDA_16_16_OFFSET
|
|
|
848 |
case R_V850_ZDA_16_16_OFFSET:
|
|
|
849 |
#endif
|
|
|
850 |
#ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
|
|
|
851 |
case R_V850_ZDA_16_16_SPLIT_OFFSET:
|
|
|
852 |
#endif
|
|
|
853 |
/* Can't support zero-relocations. */
|
|
|
854 |
printf ("ERROR: %s+0x%x: zero relocations not supported\n",
|
|
|
855 |
sym_name, q->addend);
|
|
|
856 |
continue;
|
|
|
857 |
#endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
|
|
|
858 |
#endif /* TARGET_v850 */
|
|
|
859 |
|
|
|
860 |
#ifdef TARGET_h8300
|
|
|
861 |
case R_H8_DIR24R8:
|
|
|
862 |
if (sym_reloc_size != 4) {
|
|
|
863 |
printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
|
|
|
864 |
bad_relocs++;
|
|
|
865 |
continue;
|
|
|
866 |
}
|
|
|
867 |
relocation_needed = 1;
|
|
|
868 |
sym_addr = (*(q->sym_ptr_ptr))->value;
|
|
|
869 |
q->address -= 1;
|
|
|
870 |
r_mem -= 1; /* tracks q->address */
|
|
|
871 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
872 |
sym_addr += sym_vma + q->addend;
|
|
|
873 |
sym_addr |= (*(unsigned char *)r_mem<<24);
|
|
|
874 |
break;
|
|
|
875 |
case R_H8_DIR24A8:
|
|
|
876 |
if (sym_reloc_size != 4) {
|
|
|
877 |
printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
|
|
|
878 |
bad_relocs++;
|
|
|
879 |
continue;
|
|
|
880 |
}
|
|
|
881 |
/* Absolute symbol done not relocation */
|
|
|
882 |
relocation_needed = !bfd_is_abs_section(sym_section);
|
|
|
883 |
sym_addr = (*(q->sym_ptr_ptr))->value;
|
|
|
884 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
885 |
sym_addr += sym_vma + q->addend;
|
|
|
886 |
break;
|
|
|
887 |
case R_H8_DIR32:
|
|
|
888 |
case R_H8_DIR32A16: /* currently 32, could be made 16 */
|
|
|
889 |
if (sym_reloc_size != 4) {
|
|
|
890 |
printf("R_H8_DIR32 size %d\n", sym_reloc_size);
|
|
|
891 |
bad_relocs++;
|
|
|
892 |
continue;
|
|
|
893 |
}
|
|
|
894 |
relocation_needed = 1;
|
|
|
895 |
sym_addr = (*(q->sym_ptr_ptr))->value;
|
|
|
896 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
897 |
sym_addr += sym_vma + q->addend;
|
|
|
898 |
break;
|
|
|
899 |
case R_H8_PCREL16:
|
|
|
900 |
sym_vma = 0;
|
|
|
901 |
sym_addr = (*(q->sym_ptr_ptr))->value;
|
|
|
902 |
sym_addr += sym_vma + q->addend;
|
|
|
903 |
sym_addr -= (q->address + 2);
|
|
|
904 |
if (bfd_big_endian(abs_bfd))
|
|
|
905 |
*(unsigned short *)r_mem =
|
|
|
906 |
bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
|
|
|
907 |
continue;
|
|
|
908 |
case R_H8_PCREL8:
|
|
|
909 |
sym_vma = 0;
|
|
|
910 |
sym_addr = (*(q->sym_ptr_ptr))->value;
|
|
|
911 |
sym_addr += sym_vma + q->addend;
|
|
|
912 |
sym_addr -= (q->address + 1);
|
|
|
913 |
*(unsigned char *)r_mem = sym_addr;
|
|
|
914 |
continue;
|
|
|
915 |
#endif
|
|
|
916 |
|
|
|
917 |
#ifdef TARGET_microblaze
|
|
|
918 |
case R_MICROBLAZE_64:
|
|
|
919 |
/* The symbol is split over two consecutive instructions.
|
|
|
920 |
Flag this to the flat loader by setting the high bit of
|
|
|
921 |
the relocation symbol. */
|
|
|
922 |
{
|
|
|
923 |
unsigned char *p = r_mem;
|
|
|
924 |
pflags=0x80000000;
|
|
|
925 |
|
|
|
926 |
/* work out the relocation */
|
|
|
927 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
928 |
sym_addr += sym_vma + q->addend;
|
|
|
929 |
/* Write relocated pointer back */
|
|
|
930 |
p[2] = (sym_addr >> 24) & 0xff;
|
|
|
931 |
p[3] = (sym_addr >> 16) & 0xff;
|
|
|
932 |
p[6] = (sym_addr >> 8) & 0xff;
|
|
|
933 |
p[7] = sym_addr & 0xff;
|
|
|
934 |
|
|
|
935 |
/* create a new reloc entry */
|
|
|
936 |
flat_relocs = realloc(flat_relocs,
|
|
|
937 |
(flat_reloc_count + 1) * sizeof(uint32_t));
|
|
|
938 |
flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
|
|
|
939 |
flat_reloc_count++;
|
|
|
940 |
relocation_needed = 0;
|
|
|
941 |
pflags = 0;
|
|
|
942 |
sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
|
|
|
943 |
bfd_section_vma(abs_bfd, sym_section));
|
|
|
944 |
if (verbose)
|
|
|
945 |
printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
|
|
|
946 |
"section=%s size=%d "
|
|
|
947 |
"fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
|
|
|
948 |
q->address, sym_name, addstr,
|
|
|
949 |
section_name, sym_reloc_size,
|
|
|
950 |
sym_addr, section_vma + q->address);
|
|
|
951 |
if (verbose)
|
|
|
952 |
printf("reloc[%d] = 0x%x\n", flat_reloc_count,
|
|
|
953 |
section_vma + q->address);
|
|
|
954 |
|
|
|
955 |
continue;
|
|
|
956 |
}
|
|
|
957 |
case R_MICROBLAZE_32:
|
|
|
958 |
{
|
|
|
959 |
unsigned char *p = r_mem;
|
|
|
960 |
|
|
|
961 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
962 |
sym_addr += sym_vma + q->addend;
|
|
|
963 |
relocation_needed = 1;
|
|
|
964 |
break;
|
|
|
965 |
}
|
|
|
966 |
case R_MICROBLAZE_64_PCREL:
|
|
|
967 |
sym_vma = 0;
|
|
|
968 |
sym_addr += sym_vma + q->addend;
|
|
|
969 |
sym_addr -= (q->address + 4);
|
|
|
970 |
sym_addr = htonl(sym_addr);
|
|
|
971 |
/* insert 16 MSB */
|
|
|
972 |
* ((unsigned short *) (r_mem+2)) = (sym_addr) & 0xFFFF;
|
|
|
973 |
/* then 16 LSB */
|
|
|
974 |
* ((unsigned short *) (r_mem+6)) = (sym_addr >> 16) & 0xFFFF;
|
|
|
975 |
/* We've done all the work, so continue
|
|
|
976 |
to next reloc instead of break */
|
|
|
977 |
continue;
|
|
|
978 |
|
|
|
979 |
#endif /* TARGET_microblaze */
|
|
|
980 |
|
|
|
981 |
#ifdef TARGET_nios2
|
|
|
982 |
#define htoniosl(x) (x)
|
|
|
983 |
#define niostohl(x) (x)
|
|
|
984 |
case R_NIOS2_BFD_RELOC_32:
|
|
|
985 |
relocation_needed = 1;
|
|
|
986 |
pflags = (FLAT_NIOS2_R_32 << 28);
|
|
|
987 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
988 |
sym_addr += sym_vma + q->addend;
|
|
|
989 |
/* modify target, in target order */
|
|
|
990 |
*(unsigned long *)r_mem = htoniosl(sym_addr);
|
|
|
991 |
break;
|
|
|
992 |
case R_NIOS2_CALL26:
|
|
|
993 |
{
|
|
|
994 |
unsigned long exist_val;
|
|
|
995 |
relocation_needed = 1;
|
|
|
996 |
pflags = (FLAT_NIOS2_R_CALL26 << 28);
|
|
|
997 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
998 |
sym_addr += sym_vma + q->addend;
|
|
|
999 |
|
|
|
1000 |
/* modify target, in target order */
|
|
|
1001 |
// exist_val = niostohl(*(unsigned long *)r_mem);
|
|
|
1002 |
exist_val = ((sym_addr >> 2) << 6);
|
|
|
1003 |
*(unsigned long *)r_mem = htoniosl(exist_val);
|
|
|
1004 |
break;
|
|
|
1005 |
}
|
|
|
1006 |
case R_NIOS2_HIADJ16:
|
|
|
1007 |
case R_NIOS2_HI16:
|
|
|
1008 |
{
|
|
|
1009 |
unsigned long exist_val;
|
|
|
1010 |
int r2_type;
|
|
|
1011 |
/* handle the adjacent HI/LO pairs */
|
|
|
1012 |
if (relcount == 0)
|
|
|
1013 |
r2_type = R_NIOS2_NONE;
|
|
|
1014 |
else
|
|
|
1015 |
r2_type = p[1]->howto->type;
|
|
|
1016 |
if ((r2_type == R_NIOS2_LO16)
|
|
|
1017 |
&& (p[0]->sym_ptr_ptr == p[1]->sym_ptr_ptr)
|
|
|
1018 |
&& (p[0]->addend == p[1]->addend))
|
|
|
1019 |
{
|
|
|
1020 |
unsigned char * r2_mem = sectionp + p[1]->address;
|
|
|
1021 |
if (p[1]->address - q->address!=4)
|
|
|
1022 |
printf("Err: HI/LO not adjacent %d\n", p[1]->address - q->address);
|
|
|
1023 |
relocation_needed = 1;
|
|
|
1024 |
pflags = (q->howto->type == R_NIOS2_HIADJ16)
|
|
|
1025 |
? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;
|
|
|
1026 |
pflags <<= 28;
|
|
|
1027 |
|
|
|
1028 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1029 |
sym_addr += sym_vma + q->addend;
|
|
|
1030 |
|
|
|
1031 |
/* modify high 16 bits, in target order */
|
|
|
1032 |
exist_val = niostohl(*(unsigned long *)r_mem);
|
|
|
1033 |
exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
|
|
|
1034 |
if (q->howto->type == R_NIOS2_HIADJ16)
|
|
|
1035 |
exist_val |= ((((sym_addr >> 16) + ((sym_addr >> 15) & 1)) & 0xFFFF) << 6);
|
|
|
1036 |
else
|
|
|
1037 |
exist_val |= (((sym_addr >> 16) & 0xFFFF) << 6);
|
|
|
1038 |
*(unsigned long *)r_mem = htoniosl(exist_val);
|
|
|
1039 |
|
|
|
1040 |
/* modify low 16 bits, in target order */
|
|
|
1041 |
exist_val = niostohl(*(unsigned long *)r2_mem);
|
|
|
1042 |
exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
|
|
|
1043 |
exist_val |= ((sym_addr & 0xFFFF) << 6);
|
|
|
1044 |
*(unsigned long *)r2_mem = htoniosl(exist_val);
|
|
|
1045 |
|
|
|
1046 |
} else
|
|
|
1047 |
goto NIOS2_RELOC_ERR;
|
|
|
1048 |
}
|
|
|
1049 |
break;
|
|
|
1050 |
|
|
|
1051 |
case R_NIOS2_GPREL:
|
|
|
1052 |
{
|
|
|
1053 |
unsigned long exist_val, temp;
|
|
|
1054 |
//long gp = get_symbol_offset("_gp", sym_section, symbols, number_of_symbols);
|
|
|
1055 |
long gp = get_gp_value(symbols, number_of_symbols);
|
|
|
1056 |
if (gp == -1) {
|
|
|
1057 |
printf("Err: unresolved symbol _gp when relocating %s\n", sym_name);
|
|
|
1058 |
goto NIOS2_RELOC_ERR;
|
|
|
1059 |
}
|
|
|
1060 |
/* _gp holds a absolute value, otherwise the ld cannot generate correct code */
|
|
|
1061 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1062 |
//printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);
|
|
|
1063 |
sym_addr += sym_vma + q->addend;
|
|
|
1064 |
sym_addr -= gp;
|
|
|
1065 |
//printf("sym - _gp=%x, %d\n", sym_addr, sym_addr);
|
|
|
1066 |
/* modify the target, in target order (little_endian) */
|
|
|
1067 |
exist_val = niostohl(*(unsigned long *)r_mem);
|
|
|
1068 |
temp = ((exist_val >> 6) & 0x3ff0000) | (sym_addr & 0xffff);
|
|
|
1069 |
temp <<= 6;
|
|
|
1070 |
temp |= (exist_val & 0x3f);
|
|
|
1071 |
*(unsigned long *)r_mem = htoniosl(temp);
|
|
|
1072 |
if (verbose)
|
|
|
1073 |
printf("omit: offset=0x%x symbol=%s%s "
|
|
|
1074 |
"section=%s size=%d "
|
|
|
1075 |
"fixup=0x%x (reloc=0x%x) GPREL\n",
|
|
|
1076 |
q->address, sym_name, addstr,
|
|
|
1077 |
section_name, sym_reloc_size,
|
|
|
1078 |
sym_addr, section_vma + q->address);
|
|
|
1079 |
continue;
|
|
|
1080 |
}
|
|
|
1081 |
case R_NIOS2_PCREL16:
|
|
|
1082 |
{
|
|
|
1083 |
unsigned long exist_val;
|
|
|
1084 |
sym_vma = 0;
|
|
|
1085 |
sym_addr += sym_vma + q->addend;
|
|
|
1086 |
sym_addr -= (q->address + 4);
|
|
|
1087 |
/* modify the target, in target order (little_endian) */
|
|
|
1088 |
exist_val = niostohl(*(unsigned long *)r_mem);
|
|
|
1089 |
exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
|
|
|
1090 |
exist_val |= ((sym_addr & 0xFFFF) << 6);
|
|
|
1091 |
*(unsigned long *)r_mem = htoniosl(exist_val);
|
|
|
1092 |
if (verbose)
|
|
|
1093 |
printf("omit: offset=0x%x symbol=%s%s "
|
|
|
1094 |
"section=%s size=%d "
|
|
|
1095 |
"fixup=0x%x (reloc=0x%x) PCREL\n",
|
|
|
1096 |
q->address, sym_name, addstr,
|
|
|
1097 |
section_name, sym_reloc_size,
|
|
|
1098 |
sym_addr, section_vma + q->address);
|
|
|
1099 |
continue;
|
|
|
1100 |
}
|
|
|
1101 |
|
|
|
1102 |
case R_NIOS2_LO16:
|
|
|
1103 |
/* check if this is actually the 2nd half of a pair */
|
|
|
1104 |
if ((p > relpp)
|
|
|
1105 |
&& ((p[-1]->howto->type == R_NIOS2_HIADJ16)
|
|
|
1106 |
|| (p[-1]->howto->type == R_NIOS2_HI16))
|
|
|
1107 |
&& (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
|
|
|
1108 |
&& (p[-1]->addend == p[0]->addend)) {
|
|
|
1109 |
if (verbose)
|
|
|
1110 |
printf("omit: offset=0x%x symbol=%s%s "
|
|
|
1111 |
"section=%s size=%d LO16\n",
|
|
|
1112 |
q->address, sym_name, addstr,
|
|
|
1113 |
section_name, sym_reloc_size);
|
|
|
1114 |
continue;
|
|
|
1115 |
}
|
|
|
1116 |
|
|
|
1117 |
/* error, fall through */
|
|
|
1118 |
|
|
|
1119 |
case R_NIOS2_S16:
|
|
|
1120 |
case R_NIOS2_U16:
|
|
|
1121 |
case R_NIOS2_CACHE_OPX:
|
|
|
1122 |
case R_NIOS2_IMM5:
|
|
|
1123 |
case R_NIOS2_IMM6:
|
|
|
1124 |
case R_NIOS2_IMM8:
|
|
|
1125 |
case R_NIOS2_BFD_RELOC_16:
|
|
|
1126 |
case R_NIOS2_BFD_RELOC_8:
|
|
|
1127 |
case R_NIOS2_GNU_VTINHERIT:
|
|
|
1128 |
case R_NIOS2_GNU_VTENTRY:
|
|
|
1129 |
case R_NIOS2_UJMP:
|
|
|
1130 |
case R_NIOS2_CJMP:
|
|
|
1131 |
case R_NIOS2_CALLR:
|
|
|
1132 |
NIOS2_RELOC_ERR:
|
|
|
1133 |
printf("Err: unexpected reloc type %s(%d)\n", q->howto->name, q->howto->type);
|
|
|
1134 |
bad_relocs++;
|
|
|
1135 |
continue;
|
|
|
1136 |
#endif /* TARGET_nios2 */
|
|
|
1137 |
|
|
|
1138 |
#ifdef TARGET_sparc
|
|
|
1139 |
case R_SPARC_32:
|
|
|
1140 |
case R_SPARC_UA32:
|
|
|
1141 |
relocation_needed = 1;
|
|
|
1142 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1143 |
sym_addr += sym_vma + q->addend;
|
|
|
1144 |
break;
|
|
|
1145 |
case R_SPARC_PC22:
|
|
|
1146 |
sym_vma = 0;
|
|
|
1147 |
sym_addr += sym_vma + q->addend;
|
|
|
1148 |
sym_addr -= q->address;
|
|
|
1149 |
break;
|
|
|
1150 |
case R_SPARC_WDISP30:
|
|
|
1151 |
sym_addr = (((*(q->sym_ptr_ptr))->value-
|
|
|
1152 |
q->address) >> 2) & 0x3fffffff;
|
|
|
1153 |
sym_addr |= (
|
|
|
1154 |
ntohl(*(uint32_t *)r_mem)
|
|
|
1155 |
& 0xc0000000
|
|
|
1156 |
);
|
|
|
1157 |
break;
|
|
|
1158 |
case R_SPARC_HI22:
|
|
|
1159 |
relocation_needed = 1;
|
|
|
1160 |
pflags = 0x80000000;
|
|
|
1161 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1162 |
sym_addr += sym_vma + q->addend;
|
|
|
1163 |
sym_addr |= (
|
|
|
1164 |
htonl(*(uint32_t *)r_mem)
|
|
|
1165 |
& 0xffc00000
|
|
|
1166 |
);
|
|
|
1167 |
break;
|
|
|
1168 |
case R_SPARC_LO10:
|
|
|
1169 |
relocation_needed = 1;
|
|
|
1170 |
pflags = 0x40000000;
|
|
|
1171 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1172 |
sym_addr += sym_vma + q->addend;
|
|
|
1173 |
sym_addr &= 0x000003ff;
|
|
|
1174 |
sym_addr |= (
|
|
|
1175 |
htonl(*(uint32_t *)r_mem)
|
|
|
1176 |
& 0xfffffc00
|
|
|
1177 |
);
|
|
|
1178 |
break;
|
|
|
1179 |
#endif /* TARGET_sparc */
|
|
|
1180 |
|
|
|
1181 |
|
|
|
1182 |
#ifdef TARGET_sh
|
|
|
1183 |
case R_SH_DIR32:
|
|
|
1184 |
relocation_needed = 1;
|
|
|
1185 |
sym_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1186 |
sym_addr += sym_vma + q->addend;
|
|
|
1187 |
break;
|
|
|
1188 |
case R_SH_REL32:
|
|
|
1189 |
sym_vma = 0;
|
|
|
1190 |
sym_addr += sym_vma + q->addend;
|
|
|
1191 |
sym_addr -= q->address;
|
|
|
1192 |
break;
|
|
|
1193 |
#endif /* TARGET_sh */
|
|
|
1194 |
|
|
|
1195 |
#ifdef TARGET_e1
|
|
|
1196 |
#define htoe1l(x) htonl(x)
|
|
|
1197 |
|
|
|
1198 |
#if 0
|
|
|
1199 |
#define DEBUG_E1
|
|
|
1200 |
#endif
|
|
|
1201 |
|
|
|
1202 |
#ifdef DEBUG_E1
|
|
|
1203 |
#define DBG_E1 printf
|
|
|
1204 |
#else
|
|
|
1205 |
#define DBG_E1(x, ... )
|
|
|
1206 |
#endif
|
|
|
1207 |
|
|
|
1208 |
#define _32BITS_RELOC 0x00000000
|
|
|
1209 |
#define _30BITS_RELOC 0x80000000
|
|
|
1210 |
#define _28BITS_RELOC 0x40000000
|
|
|
1211 |
{
|
|
|
1212 |
char *p;
|
|
|
1213 |
unsigned long sec_vma, exist_val, S;
|
|
|
1214 |
case R_E1_CONST31:
|
|
|
1215 |
relocation_needed = 1;
|
|
|
1216 |
DBG_E1("Handling Reloc <CONST31>\n");
|
|
|
1217 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1218 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
|
|
|
1219 |
sec_vma, sym_addr, q->address);
|
|
|
1220 |
sym_addr = sec_vma + sym_addr;
|
|
|
1221 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
|
|
|
1222 |
DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
|
|
|
1223 |
exist_val = htoe1l(exist_val);
|
|
|
1224 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
|
|
|
1225 |
sym_addr += exist_val;
|
|
|
1226 |
pflags = _30BITS_RELOC;
|
|
|
1227 |
break;
|
|
|
1228 |
case R_E1_CONST31_PCREL:
|
|
|
1229 |
relocation_needed = 0;
|
|
|
1230 |
DBG_E1("Handling Reloc <CONST31_PCREL>\n");
|
|
|
1231 |
DBG_E1("DONT RELOCATE AT LOADING\n");
|
|
|
1232 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1233 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
|
|
|
1234 |
sec_vma, sym_addr, q->address);
|
|
|
1235 |
sym_addr = sec_vma + sym_addr;
|
|
|
1236 |
DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
|
|
|
1237 |
|
|
|
1238 |
DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
|
|
|
1239 |
section_vma );
|
|
|
1240 |
q->address = q->address + section_vma;
|
|
|
1241 |
DBG_E1("q->address += section_vma : 0x%x\n", q->address );
|
|
|
1242 |
|
|
|
1243 |
if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
|
|
|
1244 |
DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
|
|
|
1245 |
DBG_E1( "sym_addr := sym_addr - q->address - "
|
|
|
1246 |
"sizeof(CONST31_PCREL): [0x%x]\n",
|
|
|
1247 |
sym_addr );
|
|
|
1248 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
|
|
|
1249 |
DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
|
|
|
1250 |
exist_val = htoe1l(exist_val);
|
|
|
1251 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
|
|
|
1252 |
sym_addr |= exist_val;
|
|
|
1253 |
DBG_E1("sym_addr |= exist_val) : [0x%x]\n", sym_addr );
|
|
|
1254 |
break;
|
|
|
1255 |
case R_E1_DIS29W_PCREL:
|
|
|
1256 |
relocation_needed = 0;
|
|
|
1257 |
DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
|
|
|
1258 |
DBG_E1("DONT RELOCATE AT LOADING\n");
|
|
|
1259 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1260 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
|
|
|
1261 |
sec_vma, sym_addr, q->address);
|
|
|
1262 |
sym_addr = sec_vma + sym_addr;
|
|
|
1263 |
DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
|
|
|
1264 |
|
|
|
1265 |
DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
|
|
|
1266 |
section_vma );
|
|
|
1267 |
q->address = q->address + section_vma;
|
|
|
1268 |
DBG_E1("q->address += section_vma : 0x%x\n", q->address );
|
|
|
1269 |
|
|
|
1270 |
if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
|
|
|
1271 |
DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
|
|
|
1272 |
DBG_E1( "sym_addr := sym_addr - q->address - "
|
|
|
1273 |
"sizeof(CONST31_PCREL): [0x%x]\n",
|
|
|
1274 |
sym_addr );
|
|
|
1275 |
DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
|
|
|
1276 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
|
|
|
1277 |
DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
|
|
|
1278 |
exist_val = htoe1l(exist_val);
|
|
|
1279 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
|
|
|
1280 |
sym_addr += exist_val;
|
|
|
1281 |
break;
|
|
|
1282 |
case R_E1_DIS29W:
|
|
|
1283 |
DBG_E1("Handling Reloc <DIS29W>\n");
|
|
|
1284 |
goto DIS29_RELOCATION;
|
|
|
1285 |
case R_E1_DIS29H:
|
|
|
1286 |
DBG_E1("Handling Reloc <DIS29H>\n");
|
|
|
1287 |
goto DIS29_RELOCATION;
|
|
|
1288 |
case R_E1_DIS29B:
|
|
|
1289 |
DBG_E1("Handling Reloc <DIS29B>\n");
|
|
|
1290 |
DIS29_RELOCATION:
|
|
|
1291 |
relocation_needed = 1;
|
|
|
1292 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1293 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
|
|
|
1294 |
sec_vma, sym_addr);
|
|
|
1295 |
sym_addr = sec_vma + sym_addr;
|
|
|
1296 |
DBG_E1("sym_addr = sec_vma + sym_addr : [0x%08x]\n", sym_addr);
|
|
|
1297 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
|
|
|
1298 |
DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
|
|
|
1299 |
exist_val = htoe1l(exist_val);
|
|
|
1300 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
|
|
|
1301 |
sym_addr += exist_val;
|
|
|
1302 |
DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
|
|
|
1303 |
pflags = _28BITS_RELOC;
|
|
|
1304 |
break;
|
|
|
1305 |
case R_E1_IMM32_PCREL:
|
|
|
1306 |
relocation_needed = 0;
|
|
|
1307 |
DBG_E1("Handling Reloc <IMM32_PCREL>\n");
|
|
|
1308 |
DBG_E1("DONT RELOCATE AT LOADING\n");
|
|
|
1309 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1310 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
|
|
|
1311 |
sec_vma, sym_addr);
|
|
|
1312 |
sym_addr = sec_vma + sym_addr;
|
|
|
1313 |
|
|
|
1314 |
DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
|
|
|
1315 |
DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
|
|
|
1316 |
section_vma );
|
|
|
1317 |
q->address = q->address + section_vma;
|
|
|
1318 |
DBG_E1("q->address += section_vma : 0x%x\n", q->address );
|
|
|
1319 |
|
|
|
1320 |
if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )
|
|
|
1321 |
DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
|
|
|
1322 |
DBG_E1( "sym_addr := sym_addr - q->address - "
|
|
|
1323 |
"sizeof(CONST31_PCREL): [0x%x]\n",
|
|
|
1324 |
sym_addr );
|
|
|
1325 |
DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
|
|
|
1326 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
|
|
|
1327 |
DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
|
|
|
1328 |
exist_val = htoe1l(exist_val);
|
|
|
1329 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
|
|
|
1330 |
sym_addr += exist_val;
|
|
|
1331 |
break;
|
|
|
1332 |
case R_E1_IMM32:
|
|
|
1333 |
relocation_needed = 1;
|
|
|
1334 |
DBG_E1("Handling Reloc <IMM32>\n");
|
|
|
1335 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1336 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
|
|
|
1337 |
sec_vma, sym_addr);
|
|
|
1338 |
sym_addr = sec_vma + sym_addr;
|
|
|
1339 |
DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
|
|
|
1340 |
DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
|
|
|
1341 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
|
|
|
1342 |
DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
|
|
|
1343 |
exist_val = htoe1l(exist_val);
|
|
|
1344 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
|
|
|
1345 |
sym_addr += exist_val;
|
|
|
1346 |
pflags = _32BITS_RELOC;
|
|
|
1347 |
break;
|
|
|
1348 |
case R_E1_WORD:
|
|
|
1349 |
relocation_needed = 1;
|
|
|
1350 |
DBG_E1("Handling Reloc <WORD>\n");
|
|
|
1351 |
sec_vma = bfd_section_vma(abs_bfd, sym_section);
|
|
|
1352 |
DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
|
|
|
1353 |
sec_vma, sym_addr);
|
|
|
1354 |
sym_addr = sec_vma + sym_addr;
|
|
|
1355 |
DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
|
|
|
1356 |
exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );
|
|
|
1357 |
DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
|
|
|
1358 |
exist_val = htoe1l(exist_val);
|
|
|
1359 |
DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
|
|
|
1360 |
sym_addr += exist_val;
|
|
|
1361 |
DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
|
|
|
1362 |
pflags = _32BITS_RELOC;
|
|
|
1363 |
break;
|
|
|
1364 |
}
|
|
|
1365 |
#undef _32BITS_RELOC
|
|
|
1366 |
#undef _30BITS_RELOC
|
|
|
1367 |
#undef _28BITS_RELOC
|
|
|
1368 |
#endif
|
|
|
1369 |
default:
|
|
|
1370 |
/* missing support for other types of relocs */
|
|
|
1371 |
printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
|
|
|
1372 |
bad_relocs++;
|
|
|
1373 |
continue;
|
|
|
1374 |
}
|
|
|
1375 |
}
|
|
|
1376 |
|
|
|
1377 |
sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
|
|
|
1378 |
bfd_section_vma(abs_bfd, sym_section));
|
|
|
1379 |
|
|
|
1380 |
|
| 491 |
theseven |
1381 |
#if 0
|
|
|
1382 |
/*
|
| 445 |
theseven |
1383 |
* for full elf relocation we have to write back the
|
|
|
1384 |
* start_code relative value to use.
|
|
|
1385 |
*/
|
|
|
1386 |
if (!pic_with_got) {
|
|
|
1387 |
#if defined(TARGET_arm)
|
|
|
1388 |
union {
|
|
|
1389 |
unsigned char c[4];
|
|
|
1390 |
uint32_t l;
|
|
|
1391 |
} tmp;
|
|
|
1392 |
int32_t hl;
|
|
|
1393 |
int i0, i1, i2, i3;
|
|
|
1394 |
|
|
|
1395 |
/*
|
|
|
1396 |
* horrible nasty hack to support different endianess
|
|
|
1397 |
*/
|
|
|
1398 |
if (!bfd_big_endian(abs_bfd)) {
|
|
|
1399 |
i0 = 0;
|
|
|
1400 |
i1 = 1;
|
|
|
1401 |
i2 = 2;
|
|
|
1402 |
i3 = 3;
|
|
|
1403 |
} else {
|
|
|
1404 |
i0 = 3;
|
|
|
1405 |
i1 = 2;
|
|
|
1406 |
i2 = 1;
|
|
|
1407 |
i3 = 0;
|
|
|
1408 |
}
|
|
|
1409 |
|
|
|
1410 |
tmp.l = *(uint32_t *)r_mem;
|
|
|
1411 |
hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
|
|
|
1412 |
if (use_resolved ||
|
|
|
1413 |
(((*p)->howto->type != R_ARM_PC24) &&
|
|
|
1414 |
((*p)->howto->type != R_ARM_PLT32)))
|
|
|
1415 |
hl |= (tmp.c[i3] << 24);
|
|
|
1416 |
else if (tmp.c[i2] & 0x80)
|
|
|
1417 |
hl |= 0xff000000; /* sign extend */
|
|
|
1418 |
if (!use_resolved)
|
|
|
1419 |
hl += sym_addr;
|
|
|
1420 |
tmp.c[i0] = hl & 0xff;
|
|
|
1421 |
tmp.c[i1] = (hl >> 8) & 0xff;
|
|
|
1422 |
tmp.c[i2] = (hl >> 16) & 0xff;
|
|
|
1423 |
if (use_resolved ||
|
|
|
1424 |
(((*p)->howto->type != R_ARM_PC24) &&
|
|
|
1425 |
((*p)->howto->type != R_ARM_PLT32)))
|
|
|
1426 |
tmp.c[i3] = (hl >> 24) & 0xff;
|
|
|
1427 |
if ((*p)->howto->type == R_ARM_ABS32)
|
| 449 |
theseven |
1428 |
*(uint32_t *)r_mem = hl;
|
| 445 |
theseven |
1429 |
else
|
|
|
1430 |
*(uint32_t *)r_mem = tmp.l;
|
|
|
1431 |
#elif defined(TARGET_e1)
|
|
|
1432 |
#define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/
|
|
|
1433 |
switch ((*p)->howto->type) {
|
|
|
1434 |
case R_E1_CONST31:
|
|
|
1435 |
case R_E1_CONST31_PCREL:
|
|
|
1436 |
case R_E1_DIS29W_PCREL:
|
|
|
1437 |
case R_E1_DIS29W:
|
|
|
1438 |
case R_E1_DIS29H:
|
|
|
1439 |
case R_E1_DIS29B:
|
|
|
1440 |
case R_E1_IMM32_PCREL:
|
|
|
1441 |
case R_E1_IMM32:
|
|
|
1442 |
DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",
|
|
|
1443 |
(sectionp + q->address + 2), sym_addr );
|
|
|
1444 |
*((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =
|
|
|
1445 |
htonl(sym_addr);
|
|
|
1446 |
break;
|
|
|
1447 |
case R_E1_WORD:
|
|
|
1448 |
DBG_E1("In addr : [0x%x] <- write [0x%x]\n",
|
|
|
1449 |
(sectionp + q->address), sym_addr );
|
|
|
1450 |
*((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);
|
|
|
1451 |
break;
|
|
|
1452 |
default:
|
|
|
1453 |
printf("ERROR:Unhandled Relocation. Exiting...\n");
|
|
|
1454 |
exit(0);
|
|
|
1455 |
break;
|
|
|
1456 |
}
|
|
|
1457 |
#elif defined TARGET_bfin
|
|
|
1458 |
if ((*p)->howto->type == R_BFIN_RIMM16
|
|
|
1459 |
|| (*p)->howto->type == R_BFIN_HUIMM16
|
|
|
1460 |
|| (*p)->howto->type == R_BFIN_LUIMM16)
|
|
|
1461 |
{
|
|
|
1462 |
/* for l and h we set the lower 16 bits which is only when it will be used */
|
|
|
1463 |
bfd_putl16 (sym_addr, sectionp + q->address);
|
|
|
1464 |
} else if ((*p)->howto->type == R_BFIN_BYTE4_DATA) {
|
|
|
1465 |
bfd_putl32 (sym_addr, sectionp + q->address);
|
|
|
1466 |
}
|
|
|
1467 |
#else /* ! TARGET_arm && ! TARGET_e1 && ! TARGET_bfin */
|
|
|
1468 |
|
|
|
1469 |
switch (q->howto->type) {
|
|
|
1470 |
#ifdef TARGET_v850
|
|
|
1471 |
case R_V850_HI16_S:
|
|
|
1472 |
case R_V850_HI16:
|
|
|
1473 |
case R_V850_LO16:
|
|
|
1474 |
/* Do nothing -- for cases we handle,
|
|
|
1475 |
the bits produced by the linker are
|
|
|
1476 |
what we want in the final flat file
|
|
|
1477 |
(and other cases are errors). Note
|
|
|
1478 |
that unlike most relocated values,
|
|
|
1479 |
it is stored in little-endian order,
|
|
|
1480 |
but this is necessary to avoid
|
|
|
1481 |
trashing the low-bit, and the float
|
|
|
1482 |
loaders knows about it. */
|
|
|
1483 |
break;
|
|
|
1484 |
#endif /* TARGET_V850 */
|
|
|
1485 |
|
|
|
1486 |
#ifdef TARGET_nios2
|
|
|
1487 |
case R_NIOS2_BFD_RELOC_32:
|
|
|
1488 |
case R_NIOS2_CALL26:
|
|
|
1489 |
case R_NIOS2_HIADJ16:
|
|
|
1490 |
case R_NIOS2_HI16:
|
|
|
1491 |
/* do nothing */
|
|
|
1492 |
break;
|
|
|
1493 |
#endif /* TARGET_nios2 */
|
|
|
1494 |
|
|
|
1495 |
#if defined(TARGET_m68k)
|
|
|
1496 |
case R_68K_PC16:
|
|
|
1497 |
if (sym_addr < -0x8000 || sym_addr > 0x7fff) {
|
|
|
1498 |
fprintf (stderr, "Relocation overflow for R_68K_PC16 relocation against %s\n", sym_name);
|
|
|
1499 |
bad_relocs++;
|
|
|
1500 |
} else {
|
|
|
1501 |
r_mem[0] = (sym_addr >> 8) & 0xff;
|
|
|
1502 |
r_mem[1] = sym_addr & 0xff;
|
|
|
1503 |
}
|
|
|
1504 |
break;
|
|
|
1505 |
#endif
|
|
|
1506 |
|
|
|
1507 |
default:
|
|
|
1508 |
/* The alignment of the build host
|
|
|
1509 |
might be stricter than that of the
|
|
|
1510 |
target, so be careful. We store in
|
|
|
1511 |
network byte order. */
|
|
|
1512 |
r_mem[0] = (sym_addr >> 24) & 0xff;
|
|
|
1513 |
r_mem[1] = (sym_addr >> 16) & 0xff;
|
|
|
1514 |
r_mem[2] = (sym_addr >> 8) & 0xff;
|
|
|
1515 |
r_mem[3] = sym_addr & 0xff;
|
|
|
1516 |
}
|
|
|
1517 |
#endif /* !TARGET_arm */
|
|
|
1518 |
}
|
| 491 |
theseven |
1519 |
#endif
|
| 445 |
theseven |
1520 |
|
|
|
1521 |
if (verbose)
|
|
|
1522 |
printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
|
|
|
1523 |
"section=%s size=%d "
|
|
|
1524 |
"fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
|
|
|
1525 |
q->address, sym_name, addstr,
|
|
|
1526 |
section_name, sym_reloc_size,
|
|
|
1527 |
sym_addr, section_vma + q->address);
|
|
|
1528 |
|
|
|
1529 |
/*
|
|
|
1530 |
* Create relocation entry (PC relative doesn't need this).
|
|
|
1531 |
*/
|
|
|
1532 |
if (relocation_needed) {
|
|
|
1533 |
#ifndef TARGET_bfin
|
|
|
1534 |
flat_relocs = realloc(flat_relocs,
|
|
|
1535 |
(flat_reloc_count + 1) * sizeof(uint32_t));
|
|
|
1536 |
#ifndef TARGET_e1
|
|
|
1537 |
flat_relocs[flat_reloc_count] = pflags |
|
|
|
1538 |
(section_vma + q->address);
|
|
|
1539 |
|
|
|
1540 |
if (verbose)
|
|
|
1541 |
printf("reloc[%d] = 0x%x\n", flat_reloc_count,
|
|
|
1542 |
section_vma + q->address);
|
|
|
1543 |
#else
|
|
|
1544 |
switch ((*p)->howto->type) {
|
|
|
1545 |
case R_E1_CONST31:
|
|
|
1546 |
case R_E1_CONST31_PCREL:
|
|
|
1547 |
case R_E1_DIS29W_PCREL:
|
|
|
1548 |
case R_E1_DIS29W:
|
|
|
1549 |
case R_E1_DIS29H:
|
|
|
1550 |
case R_E1_DIS29B:
|
|
|
1551 |
case R_E1_IMM32_PCREL:
|
|
|
1552 |
case R_E1_IMM32:
|
|
|
1553 |
flat_relocs[flat_reloc_count] = pflags |
|
|
|
1554 |
(section_vma + q->address + OPCODE_SIZE);
|
|
|
1555 |
if (verbose)
|
|
|
1556 |
printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
|
|
|
1557 |
flat_relocs[flat_reloc_count] );
|
|
|
1558 |
break;
|
|
|
1559 |
case R_E1_WORD:
|
|
|
1560 |
flat_relocs[flat_reloc_count] = pflags |
|
|
|
1561 |
(section_vma + q->address);
|
|
|
1562 |
if (verbose)
|
|
|
1563 |
printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
|
|
|
1564 |
flat_relocs[flat_reloc_count] );
|
|
|
1565 |
break;
|
|
|
1566 |
}
|
|
|
1567 |
#endif
|
|
|
1568 |
flat_reloc_count++;
|
|
|
1569 |
#endif //TARGET_bfin
|
|
|
1570 |
relocation_needed = 0;
|
|
|
1571 |
pflags = 0;
|
|
|
1572 |
}
|
|
|
1573 |
|
|
|
1574 |
#if 0
|
|
|
1575 |
printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
|
|
|
1576 |
__FILE__, __LINE__, sym_name, q->address, section_name,
|
|
|
1577 |
flat_relocs[flat_reloc_count]);
|
|
|
1578 |
#endif
|
|
|
1579 |
}
|
|
|
1580 |
}
|
|
|
1581 |
}
|
|
|
1582 |
|
|
|
1583 |
if (bad_relocs) {
|
|
|
1584 |
printf("%d bad relocs\n", bad_relocs);
|
|
|
1585 |
exit(1);
|
|
|
1586 |
}
|
|
|
1587 |
|
|
|
1588 |
if (rc < 0)
|
|
|
1589 |
return(0);
|
|
|
1590 |
|
|
|
1591 |
*n_relocs = flat_reloc_count;
|
|
|
1592 |
return flat_relocs;
|
|
|
1593 |
}
|
|
|
1594 |
|
|
|
1595 |
|
|
|
1596 |
|
|
|
1597 |
static void usage(void)
|
|
|
1598 |
{
|
|
|
1599 |
fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
|
|
|
1600 |
"[-o <output-file>] <elf-file>\n\n"
|
|
|
1601 |
" -v : verbose operation\n"
|
| 466 |
theseven |
1602 |
" -l : the file to be processed is a shared library\n"
|
| 445 |
theseven |
1603 |
" -z : compress code/data/relocs\n"
|
|
|
1604 |
" -a : use existing symbol references\n"
|
|
|
1605 |
" instead of recalculating from\n"
|
|
|
1606 |
" relocation info\n"
|
| 450 |
theseven |
1607 |
" -R reloc-file : read relocations from a separate file\n"
|
| 445 |
theseven |
1608 |
" -p abs-pic-file : GOT/PIC processing with files\n"
|
|
|
1609 |
" -s stacksize : set application stack size\n"
|
|
|
1610 |
" -o output-file : output file name\n\n",
|
|
|
1611 |
elf2flt_progname);
|
|
|
1612 |
fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
|
|
|
1613 |
exit(2);
|
|
|
1614 |
}
|
|
|
1615 |
|
|
|
1616 |
|
|
|
1617 |
/* Write NUM zeroes to STREAM. */
|
|
|
1618 |
static void write_zeroes (unsigned long num, stream *stream)
|
|
|
1619 |
{
|
|
|
1620 |
char zeroes[1024];
|
|
|
1621 |
if (num > 0) {
|
|
|
1622 |
/* It'd be nice if we could just use fseek, but that doesn't seem to
|
|
|
1623 |
work for stdio output files. */
|
|
|
1624 |
memset(zeroes, 0x00, 1024);
|
|
|
1625 |
while (num > sizeof(zeroes)) {
|
|
|
1626 |
fwrite_stream(zeroes, sizeof(zeroes), 1, stream);
|
|
|
1627 |
num -= sizeof(zeroes);
|
|
|
1628 |
}
|
|
|
1629 |
if (num > 0)
|
|
|
1630 |
fwrite_stream(zeroes, num, 1, stream);
|
|
|
1631 |
}
|
|
|
1632 |
}
|
|
|
1633 |
|
|
|
1634 |
|
|
|
1635 |
int main(int argc, char *argv[])
|
|
|
1636 |
{
|
|
|
1637 |
int fd;
|
|
|
1638 |
bfd *rel_bfd, *abs_bfd;
|
|
|
1639 |
asection *s;
|
|
|
1640 |
char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
|
|
|
1641 |
char *fname = NULL;
|
|
|
1642 |
int opt;
|
|
|
1643 |
int i;
|
|
|
1644 |
int stack;
|
|
|
1645 |
stream gf;
|
|
|
1646 |
|
|
|
1647 |
asymbol **symbol_table;
|
|
|
1648 |
long number_of_symbols;
|
|
|
1649 |
|
|
|
1650 |
uint32_t data_len = 0;
|
|
|
1651 |
uint32_t bss_len = 0;
|
|
|
1652 |
uint32_t text_len = 0;
|
|
|
1653 |
uint32_t reloc_len;
|
|
|
1654 |
|
|
|
1655 |
uint32_t data_vma = ~0;
|
|
|
1656 |
uint32_t bss_vma = ~0;
|
|
|
1657 |
uint32_t text_vma = ~0;
|
|
|
1658 |
|
|
|
1659 |
uint32_t text_offs;
|
|
|
1660 |
|
|
|
1661 |
void *text;
|
|
|
1662 |
void *data;
|
|
|
1663 |
uint32_t *reloc;
|
|
|
1664 |
|
| 450 |
theseven |
1665 |
struct emcoreapp_header hdr;
|
| 445 |
theseven |
1666 |
|
|
|
1667 |
elf2flt_progname = argv[0];
|
|
|
1668 |
xmalloc_set_program_name(elf2flt_progname);
|
|
|
1669 |
|
|
|
1670 |
if (argc < 2)
|
|
|
1671 |
usage();
|
|
|
1672 |
|
|
|
1673 |
#ifndef TARGET_e1
|
|
|
1674 |
stack = 4096;
|
|
|
1675 |
#else /* We need plenty of stack for both of them (Aggregate and Register) */
|
|
|
1676 |
stack = 0x2020;
|
|
|
1677 |
#endif
|
|
|
1678 |
|
| 466 |
theseven |
1679 |
while ((opt = getopt(argc, argv, "avzlp:s:o:R:")) != -1) {
|
| 445 |
theseven |
1680 |
switch (opt) {
|
|
|
1681 |
case 'v':
|
|
|
1682 |
verbose++;
|
|
|
1683 |
break;
|
| 466 |
theseven |
1684 |
case 'l':
|
|
|
1685 |
lib = 1;
|
| 445 |
theseven |
1686 |
break;
|
|
|
1687 |
case 'z':
|
|
|
1688 |
docompress = 1;
|
|
|
1689 |
break;
|
|
|
1690 |
case 'p':
|
|
|
1691 |
pfile = optarg;
|
|
|
1692 |
break;
|
|
|
1693 |
case 'o':
|
|
|
1694 |
ofile = optarg;
|
|
|
1695 |
break;
|
|
|
1696 |
case 'a':
|
|
|
1697 |
use_resolved = 1;
|
|
|
1698 |
break;
|
|
|
1699 |
case 's':
|
|
|
1700 |
if (sscanf(optarg, "%i", &stack) != 1) {
|
|
|
1701 |
fprintf(stderr, "%s invalid stack size %s\n", argv[0], optarg);
|
|
|
1702 |
usage();
|
|
|
1703 |
}
|
|
|
1704 |
break;
|
|
|
1705 |
case 'R':
|
|
|
1706 |
rel_file = optarg;
|
|
|
1707 |
break;
|
|
|
1708 |
default:
|
|
|
1709 |
fprintf(stderr, "%s Unknown option\n", argv[0]);
|
|
|
1710 |
usage();
|
|
|
1711 |
break;
|
|
|
1712 |
}
|
|
|
1713 |
}
|
|
|
1714 |
|
|
|
1715 |
|
|
|
1716 |
fname = argv[argc-1];
|
|
|
1717 |
|
|
|
1718 |
if (pfile) {
|
|
|
1719 |
pic_with_got = 1;
|
|
|
1720 |
abs_file = pfile;
|
|
|
1721 |
} else
|
|
|
1722 |
abs_file = fname;
|
|
|
1723 |
|
|
|
1724 |
if (! rel_file)
|
|
|
1725 |
rel_file = fname;
|
|
|
1726 |
|
|
|
1727 |
if (!(rel_bfd = bfd_openr(rel_file, 0)))
|
|
|
1728 |
fatal_perror("Can't open '%s'", rel_file);
|
|
|
1729 |
|
|
|
1730 |
if (bfd_check_format (rel_bfd, bfd_object) == 0)
|
|
|
1731 |
fatal("File is not an object file");
|
|
|
1732 |
|
|
|
1733 |
if (abs_file == rel_file)
|
|
|
1734 |
abs_bfd = rel_bfd; /* one file does all */
|
|
|
1735 |
else {
|
|
|
1736 |
if (!(abs_bfd = bfd_openr(abs_file, 0)))
|
|
|
1737 |
fatal_perror("Can't open '%s'", abs_file);
|
|
|
1738 |
|
|
|
1739 |
if (bfd_check_format (abs_bfd, bfd_object) == 0)
|
|
|
1740 |
fatal("File is not an object file");
|
|
|
1741 |
}
|
|
|
1742 |
|
|
|
1743 |
if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC))
|
|
|
1744 |
fatal("%s: Input file contains no relocation info", rel_file);
|
|
|
1745 |
|
|
|
1746 |
if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P))
|
|
|
1747 |
/* `Absolute' file is not absolute, so neither are address
|
|
|
1748 |
contained therein. */
|
|
|
1749 |
fatal("%s: `-a' option specified with non-fully-resolved input file",
|
|
|
1750 |
bfd_get_filename (abs_bfd));
|
|
|
1751 |
|
|
|
1752 |
symbol_table = get_symbols(abs_bfd, &number_of_symbols);
|
|
|
1753 |
|
|
|
1754 |
/* Group output sections into text, data, and bss, and calc their sizes. */
|
|
|
1755 |
for (s = abs_bfd->sections; s != NULL; s = s->next) {
|
|
|
1756 |
uint32_t *vma, *len;
|
|
|
1757 |
bfd_size_type sec_size;
|
|
|
1758 |
bfd_vma sec_vma;
|
|
|
1759 |
|
|
|
1760 |
if (s->flags & SEC_CODE) {
|
|
|
1761 |
vma = &text_vma;
|
|
|
1762 |
len = &text_len;
|
|
|
1763 |
} else if (s->flags & SEC_DATA) {
|
|
|
1764 |
vma = &data_vma;
|
|
|
1765 |
len = &data_len;
|
|
|
1766 |
} else if (s->flags & SEC_ALLOC) {
|
|
|
1767 |
vma = &bss_vma;
|
|
|
1768 |
len = &bss_len;
|
|
|
1769 |
} else
|
|
|
1770 |
continue;
|
|
|
1771 |
|
|
|
1772 |
sec_size = bfd_section_size(abs_bfd, s);
|
|
|
1773 |
sec_vma = bfd_section_vma(abs_bfd, s);
|
|
|
1774 |
|
|
|
1775 |
if (sec_vma < *vma) {
|
|
|
1776 |
if (*len > 0)
|
|
|
1777 |
*len += sec_vma - *vma;
|
|
|
1778 |
else
|
|
|
1779 |
*len = sec_size;
|
|
|
1780 |
*vma = sec_vma;
|
|
|
1781 |
} else if (sec_vma + sec_size > *vma + *len)
|
|
|
1782 |
*len = sec_vma + sec_size - *vma;
|
|
|
1783 |
}
|
|
|
1784 |
|
|
|
1785 |
if (text_len == 0)
|
|
|
1786 |
fatal("%s: no .text section", abs_file);
|
|
|
1787 |
|
|
|
1788 |
text = xmalloc(text_len);
|
|
|
1789 |
|
|
|
1790 |
if (verbose)
|
|
|
1791 |
printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
|
|
|
1792 |
|
|
|
1793 |
/* Read in all text sections. */
|
|
|
1794 |
for (s = abs_bfd->sections; s != NULL; s = s->next)
|
|
|
1795 |
if (s->flags & SEC_CODE)
|
|
|
1796 |
if (!bfd_get_section_contents(abs_bfd, s,
|
|
|
1797 |
text + (s->vma - text_vma), 0,
|
|
|
1798 |
bfd_section_size(abs_bfd, s)))
|
|
|
1799 |
{
|
|
|
1800 |
fatal("read error section %s", s->name);
|
|
|
1801 |
}
|
|
|
1802 |
|
|
|
1803 |
if (data_len == 0)
|
|
|
1804 |
fatal("%s: no .data section", abs_file);
|
|
|
1805 |
data = xmalloc(data_len);
|
|
|
1806 |
|
|
|
1807 |
if (verbose)
|
|
|
1808 |
printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
|
|
|
1809 |
|
|
|
1810 |
if ((text_vma + text_len) != data_vma) {
|
|
|
1811 |
if ((text_vma + text_len) > data_vma) {
|
|
|
1812 |
printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
|
|
|
1813 |
exit(1);
|
|
|
1814 |
}
|
|
|
1815 |
if (verbose)
|
|
|
1816 |
printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
|
|
|
1817 |
data_vma, text_len);
|
|
|
1818 |
text_len = data_vma - text_vma;
|
|
|
1819 |
}
|
|
|
1820 |
|
|
|
1821 |
/* Read in all data sections. */
|
|
|
1822 |
for (s = abs_bfd->sections; s != NULL; s = s->next)
|
|
|
1823 |
if (s->flags & SEC_DATA)
|
|
|
1824 |
if (!bfd_get_section_contents(abs_bfd, s,
|
|
|
1825 |
data + (s->vma - data_vma), 0,
|
|
|
1826 |
bfd_section_size(abs_bfd, s)))
|
|
|
1827 |
{
|
|
|
1828 |
fatal("read error section %s", s->name);
|
|
|
1829 |
}
|
|
|
1830 |
|
|
|
1831 |
if (bss_vma == ~0)
|
|
|
1832 |
bss_vma = data_vma + data_len;
|
|
|
1833 |
|
|
|
1834 |
/* Put common symbols in bss. */
|
|
|
1835 |
bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
|
|
|
1836 |
|
|
|
1837 |
if (verbose)
|
|
|
1838 |
printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
|
|
|
1839 |
|
|
|
1840 |
if ((data_vma + data_len) != bss_vma) {
|
|
|
1841 |
if ((data_vma + data_len) > bss_vma) {
|
|
|
1842 |
printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
|
|
|
1843 |
data_len, bss_vma);
|
|
|
1844 |
exit(1);
|
|
|
1845 |
}
|
|
|
1846 |
if (verbose)
|
|
|
1847 |
printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
|
|
|
1848 |
bss_vma, text_len, data_len, text_len + data_len);
|
|
|
1849 |
data_len = bss_vma - data_vma;
|
|
|
1850 |
}
|
|
|
1851 |
|
|
|
1852 |
reloc = (uint32_t *)
|
|
|
1853 |
output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
|
|
|
1854 |
text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
|
|
|
1855 |
|
|
|
1856 |
if (reloc == NULL && verbose)
|
|
|
1857 |
printf("No relocations in code!\n");
|
|
|
1858 |
|
|
|
1859 |
text_offs = real_address_bits(text_vma);
|
|
|
1860 |
|
|
|
1861 |
/* Fill in the binflt_flat header */
|
| 450 |
theseven |
1862 |
memcpy(hdr.signature, "emCOexec", 8);
|
| 466 |
theseven |
1863 |
hdr.version = EMCOREAPP_HEADER_VERSION;
|
|
|
1864 |
hdr.textstart = sizeof(hdr);
|
|
|
1865 |
hdr.textsize = text_len + data_len;
|
|
|
1866 |
hdr.bsssize = bss_len;
|
|
|
1867 |
hdr.stacksize = stack;
|
|
|
1868 |
hdr.entrypoint = bfd_get_start_address(abs_bfd);
|
|
|
1869 |
hdr.relocstart = sizeof(hdr) + text_len + data_len;
|
|
|
1870 |
hdr.reloccount = reloc_len;
|
|
|
1871 |
hdr.flags = (docompress ? EMCOREAPP_FLAG_COMPRESSED : 0)
|
|
|
1872 |
| (lib ? EMCOREAPP_FLAG_LIBRARY : 0);
|
|
|
1873 |
hdr.creationtime = (uint32_t)time(NULL);
|
| 445 |
theseven |
1874 |
|
| 449 |
theseven |
1875 |
for (i=0; i<reloc_len; i++) reloc[i] = reloc[i];
|
| 445 |
theseven |
1876 |
|
|
|
1877 |
if (verbose) {
|
|
|
1878 |
printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
|
|
|
1879 |
text_len, data_len, bss_len);
|
|
|
1880 |
if (reloc)
|
|
|
1881 |
printf(", relocs=0x%04x", reloc_len);
|
|
|
1882 |
printf("\n");
|
|
|
1883 |
}
|
|
|
1884 |
|
|
|
1885 |
if (!ofile) {
|
| 450 |
theseven |
1886 |
ofile = xmalloc(strlen(fname) + 10 + 1); /* 10 to add suffix */
|
| 445 |
theseven |
1887 |
strcpy(ofile, fname);
|
| 466 |
theseven |
1888 |
if (lib) strcat(ofile, ".emcorelib");
|
|
|
1889 |
else strcat(ofile, ".emcoreapp");
|
| 445 |
theseven |
1890 |
}
|
|
|
1891 |
|
|
|
1892 |
if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0)
|
|
|
1893 |
fatal_perror("Can't open output file %s", ofile);
|
|
|
1894 |
|
|
|
1895 |
write(fd, &hdr, sizeof(hdr));
|
|
|
1896 |
close(fd);
|
|
|
1897 |
|
|
|
1898 |
if (fopen_stream_u(&gf, ofile, "a" BINARY_FILE_OPTS))
|
|
|
1899 |
fatal_perror("Can't open file %s for writing", ofile);
|
|
|
1900 |
|
|
|
1901 |
if (docompress == 1)
|
|
|
1902 |
reopen_stream_compressed(&gf);
|
|
|
1903 |
|
|
|
1904 |
/* Fill in any hole at the beginning of the text segment. */
|
|
|
1905 |
if (verbose)
|
|
|
1906 |
printf("ZERO before text len=0x%x\n", text_offs);
|
|
|
1907 |
write_zeroes(text_offs, &gf);
|
|
|
1908 |
|
|
|
1909 |
/* Write the text segment. */
|
|
|
1910 |
fwrite_stream(text, text_len, 1, &gf);
|
|
|
1911 |
|
|
|
1912 |
if (docompress == 2)
|
|
|
1913 |
reopen_stream_compressed(&gf);
|
|
|
1914 |
|
|
|
1915 |
/* Write the data segment. */
|
|
|
1916 |
fwrite_stream(data, data_len, 1, &gf);
|
|
|
1917 |
|
|
|
1918 |
if (reloc)
|
|
|
1919 |
fwrite_stream(reloc, reloc_len * 4, 1, &gf);
|
|
|
1920 |
|
|
|
1921 |
fclose_stream(&gf);
|
|
|
1922 |
|
|
|
1923 |
exit(0);
|
|
|
1924 |
}
|
|
|
1925 |
|
|
|
1926 |
|
|
|
1927 |
/*
|
|
|
1928 |
* this __MUST__ be at the VERY end of the file - do NOT move!!
|
|
|
1929 |
*
|
|
|
1930 |
* Local Variables:
|
|
|
1931 |
* c-basic-offset: 4
|
|
|
1932 |
* tab-width: 8
|
|
|
1933 |
* end:
|
|
|
1934 |
* vi: tabstop=8 shiftwidth=4 textwidth=79 noexpandtab
|
|
|
1935 |
*/
|