This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[patch] to bfd: embedded relocs for m68k ELF, part 1 of 2
- To: binutils at sources dot redhat dot com
- Subject: [patch] to bfd: embedded relocs for m68k ELF, part 1 of 2
- From: msokolov at ivan dot Harhan dot ORG (Michael Sokolov)
- Date: Sun, 10 Sep 00 22:50:38 CDT
Hi there,
As promised, I have implemented the embedded relocs feature for m68k ELF. Here
is the bfd part. It must be installed before the ld part, which will follow
right next.
--
Michael Sokolov Harhan Engineering Laboratory
Public Service Agent International Free Computing Task Force
International Engineering and Science Task Force
615 N GOOD LATIMER EXPY STE #4
DALLAS TX 75204-5852 USA
Phone: +1-214-824-7693 (Harhan Eng Lab office)
E-mail: msokolov@ivan.Harhan.ORG (ARPA TCP/SMTP) (UUCP coming soon)
2000-09-10 Michael Sokolov <msokolov@ivan.Harhan.ORG>
* elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): New function.
* bfd-in.h (bfd_m68k_elf32_create_embedded_relocs): Add declaration.
* bfd-in2.h: Regenerate.
Index: elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.16
diff -c -r1.16 elf32-m68k.c
*** elf32-m68k.c 2000/08/21 23:41:32 1.16
--- elf32-m68k.c 2000/09/11 03:46:17
***************
*** 2179,2184 ****
--- 2179,2322 ----
return true;
}
+ /* Given a .data section and a .emreloc in-memory section, store
+ relocation information into the .emreloc section which can be
+ used at runtime to relocate the section. This is called by the
+ linker when the --embedded-relocs switch is used. This is called
+ after the add_symbols entry point has been called for all the
+ objects, and before the final_link entry point is called. */
+
+ boolean
+ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *datasec;
+ asection *relsec;
+ char **errmsg;
+ {
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf32_External_Sym *extsyms;
+ Elf32_External_Sym *free_extsyms = NULL;
+ Elf_Internal_Rela *internal_relocs;
+ Elf_Internal_Rela *free_relocs = NULL;
+ Elf_Internal_Rela *irel, *irelend;
+ bfd_byte *p;
+
+ BFD_ASSERT (! info->relocateable);
+
+ *errmsg = NULL;
+
+ if (datasec->reloc_count == 0)
+ return true;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ /* Read this BFD's symbols if we haven't done so already, or get the cached
+ copy if it exists. */
+ if (symtab_hdr->contents != NULL)
+ extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
+ else
+ {
+ /* Go get them off disk. */
+ if (info.keep_memory)
+ extsyms = ((Elf32_External_Sym *)
+ bfd_alloc (abfd, symtab_hdr->sh_size));
+ else
+ extsyms = ((Elf32_External_Sym *)
+ bfd_malloc (symtab_hdr->sh_size));
+ if (extsyms == NULL)
+ goto error_return;
+ if (! info.keep_memory)
+ free_extsyms = extsyms;
+ if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+ || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)
+ != symtab_hdr->sh_size))
+ goto error_return;
+ if (info.keep_memory)
+ symtab_hdr->contents = extsyms;
+ }
+
+ /* Get a copy of the native relocations. */
+ internal_relocs = (_bfd_elf32_link_read_relocs
+ (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ info->keep_memory));
+ if (internal_relocs == NULL)
+ goto error_return;
+ if (! info->keep_memory)
+ free_relocs = internal_relocs;
+
+ relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
+ if (relsec->contents == NULL)
+ goto error_return;
+
+ p = relsec->contents;
+
+ irelend = internal_relocs + datasec->reloc_count;
+ for (irel = internal_relocs; irel < irelend; irel++, p += 12)
+ {
+ asection *targetsec;
+
+ /* We are going to write a four byte longword into the runtime
+ reloc section. The longword will be the address in the data
+ section which must be relocated. It is followed by the name
+ of the target section NUL-padded or truncated to 8
+ characters. */
+
+ /* We can only relocate absolute longword relocs at run time. */
+ if (ELF32_R_TYPE (irel->r_info) != (int) R_68K_32)
+ {
+ *errmsg = _("unsupported reloc type");
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ /* Get the target section referred to by the reloc. */
+ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+ {
+ Elf_Internal_Sym isym;
+
+ /* A local symbol. */
+ bfd_elf32_swap_symbol_in (abfd,
+ extsyms + ELF32_R_SYM (irel->r_info),
+ &isym);
+
+ targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+ }
+ else
+ {
+ unsigned long indx;
+ struct elf_link_hash_entry *h;
+
+ /* An external symbol. */
+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+ h = elf_sym_hashes (abfd)[indx];
+ BFD_ASSERT (h != NULL);
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ targetsec = h->root.u.def.section;
+ else
+ targetsec = NULL;
+ }
+
+ bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p);
+ memset (p + 4, 0, 8);
+ if (targetsec != NULL)
+ strncpy (p + 4, targetsec->output_section->name, 8);
+ }
+
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+ if (free_relocs != NULL)
+ free (free_relocs);
+ return true;
+
+ error_return:
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+ if (free_relocs != NULL)
+ free (free_relocs);
+ return false;
+ }
+
#define TARGET_BIG_SYM bfd_elf32_m68k_vec
#define TARGET_BIG_NAME "elf32-m68k"
#define ELF_MACHINE_CODE EM_68K
Index: bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.18
diff -c -r1.18 bfd-in.h
*** bfd-in.h 2000/08/22 19:33:16 1.18
--- bfd-in.h 2000/09/11 03:46:21
***************
*** 652,657 ****
--- 652,661 ----
/* Return true if address "naturally" sign extends, or -1 if not elf. */
extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+ extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
/* SunOS shared library support routines for the linker. */
extern struct bfd_link_needed_list *bfd_sunos_get_needed_list