* ELF format file handling. Extended relocation support for all of
* text and data.
*
- * (c) 2003, H8 support <davidm@snapgear.com>
+ * (c) 2003, H8 support, ktrace <davidm@snapgear.com>
* (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
* (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
* (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
#if defined(TARGET_h8300)
#include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
+#elif defined(__CYGWIN__)
+#include "cygwin-elf.h" /* Cygwin uses a local copy */
#else
#include <elf.h> /* TARGET_* ELF support for the BFD library */
#endif
#error "Don't know how to support your CPU architecture??"
#endif
+#ifdef TARGET_m68k
/*
* Define a maximum number of bytes allowed in the offset table.
* We'll fail if the table is larger than this.
* 8000 entries is a lot, trust me :-) (davidm)
*/
#define GOT_LIMIT 32767
+/*
+ * we have to mask out the shared library id here and there, this gives
+ * us the real address bits when needed
+ */
+#define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
+#else
+#define real_address_bits(x) (x)
+#endif
#ifndef O_BINARY
#define O_BINARY 0
int verbose = 0; /* extra output when running */
int pic_with_got = 0; /* do elf/got processing with PIC code */
int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
+int ktrace = 0; /* instruct loader output kernel trace on load */
int compress = 0; /* 1 = compress everything, 2 = compress data only */
int use_resolved = 0; /* If true, get the value of symbol references from */
/* the program contents, not from the relocation table. */
* otherwise do text as well
*/
if (!pic_with_got && (a->flags & SEC_CODE))
- sectionp = text;
+ sectionp = text + (a->vma - text_vma);
else if (a->flags & SEC_DATA)
- sectionp = data;
+ sectionp = data + (a->vma - data_vma);
else
continue;
still depend on the particular relocation
though. */
switch (q->howto->type) {
+ int r2_type;
#ifdef TARGET_v850
case R_V850_HI16_S:
/* We specially handle adjacent
- HI16_S/ZDA_15_16_OFFSET pairs that
- reference the same address (these
- are usually movhi/ld pairs). */
- if (relcount > 1
- && (p[1]->howto->type
- == R_V850_ZDA_15_16_OFFSET)
+ HI16_S/ZDA_15_16_OFFSET and
+ HI16_S/LO16 pairs that reference the
+ same address (these are usually
+ movhi/ld and movhi/movea pairs,
+ respectively). */
+ if (relcount == 0)
+ r2_type = R_V850_NONE;
+ else
+ r2_type = p[1]->howto->type;
+ if ((r2_type == R_V850_ZDA_15_16_OFFSET
+ || r2_type == R_V850_LO16)
&& (p[0]->sym_ptr_ptr
== p[1]->sym_ptr_ptr)
&& (p[0]->addend == p[1]->addend))
{
relocation_needed = 1;
- pflags = 0x80000000;
+
+ switch (r2_type) {
+ case R_V850_ZDA_15_16_OFFSET:
+ pflags = 0x10000000;
+ break;
+ case R_V850_LO16:
+ pflags = 0x20000000;
+ break;
+ }
/* We don't really need the
actual value -- the bits
/* Sign extend LO. */
lo = (lo ^ 0x8000)
- 0x8000;
- /* Ignore the LSB of
- LO, which is
+
+ /* Maybe ignore the LSB
+ of LO, which is
actually part of the
instruction. */
- lo &= ~1;
+ if (r2_type != R_V850_LO16)
+ lo &= ~1;
+
sym_addr =
(hi << 16)
+ lo;
}
} else
- case R_V850_HI16:
+ goto bad_v850_reloc_err;
+ break;
+
case R_V850_LO16:
- {
- printf("ERROR: reloc type %s unsupported in this context\n",
- q->howto->name);
- bad_relocs++;
- }
+ /* See if this is actually the
+ 2nd half of a pair. */
+ if (p > relpp
+ && (p[-1]->howto->type
+ == R_V850_HI16_S)
+ && (p[-1]->sym_ptr_ptr
+ == p[0]->sym_ptr_ptr)
+ && (p[-1]->addend == p[0]->addend))
+ break; /* not an error */
+ else
+ goto bad_v850_reloc_err;
+
+ case R_V850_HI16:
+ bad_v850_reloc_err:
+ printf("ERROR: reloc type %s unsupported in this context\n",
+ q->howto->name);
+ bad_relocs++;
break;
#endif /* TARGET_V850 */
+
default:
/* The default is to assume that the
relocation is relative and has
continue;
}
case R_MICROBLAZE_32:
- relocation_needed = 1;
+ {
+ unsigned char *p = r_mem;
+ unsigned long offset;
+
+ /* grab any offset from the text */
+ offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
//sym_addr = (*(q->sym_ptr_ptr))->value;
sym_vma = bfd_section_vma(abs_bfd, sym_section);
- sym_addr += sym_vma + q->addend;
- break;
+ sym_addr += offset + sym_vma + q->addend;
+ relocation_needed = 1;
+ break;
+ }
case R_MICROBLAZE_64_PCREL:
sym_vma = 0;
//sym_addr = (*(q->sym_ptr_ptr))->value;
"[-o <output-file>] <elf-file>\n\n"
" -v : verbose operation\n"
" -r : force load to RAM\n"
+ " -k : enable kernel trace on load (for debug)\n"
" -z : compress code/data/relocs\n"
" -d : compress data/relocs\n"
" -a : use existing symbol references\n"
/* It'd be nice if we could just use fseek, but that doesn't seem to
work for stdio output files. */
bzero(zeroes, 1024);
- while (num > sizeof zeroes) {
- fwrite(zeroes, num, 1, stream);
- num -= sizeof zeroes;
+ while (num > sizeof(zeroes)) {
+ fwrite(zeroes, sizeof(zeroes), 1, stream);
+ num -= sizeof(zeroes);
}
if (num > 0)
fwrite(zeroes, num, 1, stream);
unsigned long bss_vma = ~0;
unsigned long text_vma = ~0;
+ unsigned long text_offs;
+
void *text;
void *data;
unsigned long *reloc;
stack = 4096;
- while ((opt = getopt(argc, argv, "avzdrp:s:o:R:")) != -1) {
+ while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
switch (opt) {
case 'v':
verbose++;
case 'r':
load_to_ram++;
break;
+ case 'k':
+ ktrace++;
+ break;
case 'z':
compress = 1;
break;
/* Read in all text sections. */
for (s = abs_bfd->sections; s != NULL; s = s->next)
if (s->flags & SEC_CODE)
- if (bfd_get_section_contents(abs_bfd, s,
+ if (!bfd_get_section_contents(abs_bfd, s,
text + (s->vma - text_vma), 0,
- s->_raw_size) == false)
+ s->_raw_size))
{
fprintf(stderr, "read error section %s\n", s->name);
exit(2);
/* Read in all data sections. */
for (s = abs_bfd->sections; s != NULL; s = s->next)
if (s->flags & SEC_DATA)
- if (bfd_get_section_contents(abs_bfd, s,
+ if (!bfd_get_section_contents(abs_bfd, s,
data + (s->vma - data_vma), 0,
- s->_raw_size) == false)
+ s->_raw_size))
{
fprintf(stderr, "read error section %s\n", s->name);
exit(2);
if (verbose)
printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
- if ((text_vma + text_len + data_len) != bss_vma) {
- if ((text_vma + text_len + data_len) > bss_vma) {
+ if ((data_vma + data_len) != bss_vma) {
+ if ((data_vma + data_len) > bss_vma) {
printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
data_len, bss_vma);
exit(1);
if (verbose)
printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
bss_vma, text_len, data_len, text_len + data_len);
- data_len = bss_vma - data_vma;
+ data_len = bss_vma - data_vma;
}
reloc = (unsigned long *)
if (reloc == NULL)
printf("No relocations in code!\n");
+ text_offs = real_address_bits(text_vma);
+
/* Fill in the binflt_flat header */
memcpy(hdr.magic,"bFLT",4);
hdr.rev = htonl(FLAT_VERSION);
hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
- hdr.data_start = htonl(16 * 4 + text_len);
- hdr.data_end = htonl(16 * 4 + text_len + data_len);
- hdr.bss_end = htonl(16 * 4 + text_len + data_len + bss_len);
+ hdr.data_start = htonl(16 * 4 + text_offs + text_len);
+ hdr.data_end = htonl(16 * 4 + text_offs + text_len + data_len);
+ hdr.bss_end = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
hdr.stack_size = htonl(stack); /* FIXME */
- hdr.reloc_start = htonl(16 * 4 + data_vma + data_len);
+ hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
hdr.reloc_count = htonl(reloc_len);
hdr.flags = htonl(0
| (load_to_ram ? FLAT_FLAG_RAM : 0)
+ | (ktrace ? FLAT_FLAG_KTRACE : 0)
| (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
| (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
);
START_COMPRESSOR;
/* Fill in any hole at the beginning of the text segment. */
- write_zeroes (text_vma, gf);
+ if (verbose)
+ printf("ZERO before text len=0x%x\n", text_offs);
+ write_zeroes(text_offs, gf);
/* Write the text segment. */
fwrite(text, text_len, 1, gf);
if (compress == 2)
START_COMPRESSOR;
- /* Fill in any hole at the beginning of the data segment. */
- write_zeroes (data_vma - (text_vma + text_len), gf);
-
/* Write the data segment. */
fwrite(data, data_len, 1, gf);
if (reloc)
- fwrite(reloc, reloc_len*4, 1, gf);
+ fwrite(reloc, reloc_len * 4, 1, gf);
fclose(gf);