-/* Parts of a Stabs entry. */
-
-#define STRDXOFF (0)
-#define TYPEOFF (4)
-#define OTHEROFF (5)
-#define DESCOFF (6)
-#define VALOFF (8)
-#define STABSIZE (12)
-
-/* Adjust all the relocations entries after adding or inserting instructions. */
-
-static void
-adjust_all_relocations (abfd, sec, addr, endaddr, count, noadj)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
- bfd_vma endaddr;
- int count;
- int noadj;
-{
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Sym *isymbuf, *isym, *isymend;
- unsigned int shndx;
- bfd_byte *contents;
- Elf_Internal_Rela *irel, *irelend, *irelbase;
- struct elf_link_hash_entry **sym_hashes;
- struct elf_link_hash_entry **end_hashes;
- unsigned int symcount;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
-
- shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
-
- contents = elf_section_data (sec)->this_hdr.contents;
-
- irelbase = elf_section_data (sec)->relocs;
- irelend = irelbase + sec->reloc_count;
-
- for (irel = irelbase; irel < irelend; irel++)
- {
- if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE)
- {
- /* Get the value of the symbol referred to by the reloc. */
- if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
- {
- asection *sym_sec;
-
- /* A local symbol. */
- isym = isymbuf + ELF32_R_SYM (irel->r_info);
- sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
-
- if (isym->st_shndx == shndx)
- {
- bfd_vma baseaddr = BASEADDR (sec);
- bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
- + irel->r_addend;
-
- if ((baseaddr + addr + noadj) <= symval
- && symval < (baseaddr + endaddr))
- irel->r_addend += count;
- }
- }
- }
-
- /* Do this only for PC space relocations. */
- if (addr <= irel->r_offset && irel->r_offset < endaddr)
- irel->r_offset += count;
- }
-
- /* When adding an instruction back it is sometimes necessary to move any
- global or local symbol that was referencing the first instruction of
- the moved block to refer to the first instruction of the inserted block.
-
- For example adding a PAGE instruction before a CALL or JMP requires
- that any label on the CALL or JMP is moved to the PAGE insn. */
- addr += noadj;
-
- /* Adjust the local symbols defined in this section. */
- isymend = isymbuf + symtab_hdr->sh_info;
- for (isym = isymbuf; isym < isymend; isym++)
- {
- if (isym->st_shndx == shndx
- && addr <= isym->st_value
- && isym->st_value < endaddr)
- isym->st_value += count;
- }
-
- /* Now adjust the global symbols defined in this section. */
- symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
- - symtab_hdr->sh_info);
- sym_hashes = elf_sym_hashes (abfd);
- end_hashes = sym_hashes + symcount;
- for (; sym_hashes < end_hashes; sym_hashes++)
- {
- struct elf_link_hash_entry *sym_hash = *sym_hashes;
- if ((sym_hash->root.type == bfd_link_hash_defined
- || sym_hash->root.type == bfd_link_hash_defweak)
- && sym_hash->root.u.def.section == sec)
- {
- if (addr <= sym_hash->root.u.def.value
- && sym_hash->root.u.def.value < endaddr)
- {
- sym_hash->root.u.def.value += count;
- }
- }
- }
-
- return;
-}
-
-static boolean
-add_page_insn (abfd, sec, irel, misc)
- bfd *abfd;
- asection *sec;
- Elf_Internal_Rela *irel;
- struct misc *misc;
-{
- /* Note that we've changed the relocs, section contents, etc. */
- elf_section_data (sec)->relocs = misc->irelbase;
- elf_section_data (sec)->this_hdr.contents = misc->contents;
- misc->symtab_hdr->contents = (bfd_byte *) misc->isymbuf;
-
- /* Add the PAGE insn. */
- if (! ip2k_elf_relax_add_bytes (abfd, sec, irel->r_offset,
- page_opcode,
- sizeof (page_opcode),
- sizeof (page_opcode)))
- return false;
- else
- {
- Elf_Internal_Rela * jrel = irel - 1;
-
- /* Add relocation for PAGE insn added. */
- if (ELF32_R_TYPE (jrel->r_info) != R_IP2K_NONE)
- {
- bfd_byte code0, code1;
- char *msg = NULL;
-
- /* Get the opcode. */
- code0 = bfd_get_8 (abfd, misc->contents + irel->r_offset);
- code1 = bfd_get_8 (abfd, misc->contents + irel->r_offset + 1);
-
- if (IS_JMP_OPCODE (code0, code1))
- msg = "\tJMP instruction missing a preceeding PAGE instruction in %s\n\n";
-
- else if (IS_CALL_OPCODE (code0, code1))
- msg = "\tCALL instruction missing a preceeding PAGE instruction in %s\n\n";
-
- if (msg)
- {
- fprintf (stderr, "\n\t *** LINKER RELAXATION failure ***\n");
- fprintf (stderr, msg, sec->owner->filename);
- }
-
- return false;
- }
-
- jrel->r_addend = irel->r_addend;
- jrel->r_offset = irel->r_offset - sizeof (page_opcode);
- jrel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- R_IP2K_PAGE3);
- }
-
- return true;
-}
-
-/* Insert bytes into a section while relaxing. */
-
-static boolean
-ip2k_elf_relax_add_bytes (abfd, sec, addr, bytes, count, noadj)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
- const bfd_byte *bytes;
- int count;
- int noadj;
-{
- bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
- bfd_vma endaddr = sec->_cooked_size;
-
- /* Make room to insert the bytes. */
- memmove (contents + addr + count, contents + addr, endaddr - addr);
-
- /* Insert the bytes into the section. */
- memcpy (contents + addr, bytes, count);
-
- sec->_cooked_size += count;
-
- adjust_all_relocations (abfd, sec, addr, endaddr, count, noadj);
- return true;
-}
-
-/* Delete some bytes from a section while relaxing. */
-
-static boolean
-ip2k_elf_relax_delete_bytes (abfd, sec, addr, count)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
- int count;
-{
- bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
- bfd_vma endaddr = sec->_cooked_size;
-
- /* Actually delete the bytes. */
- memmove (contents + addr, contents + addr + count,
- endaddr - addr - count);
-
- sec->_cooked_size -= count;
-
- adjust_all_relocations (abfd, sec, addr + count, endaddr, -count, 0);
- return true;
-}
-
-/* -------------------------------------------------------------------- */
-
-/* XXX: The following code is the result of a cut&paste. This unfortunate
- practice is very widespread in the various target back-end files. */
-