Re: Release 2.24

Maciej W. Rozycki
2013-11-21T19:25:43Z

On Mon, 18 Nov 2013, Joel Brobecker wrote:

> > I see 2.24 is about to roll out, so I'll try to find some time this week
> > to make the necessary adjustments for a matching GDB 7.6.2 maintenance
> > release -- assuming as per your recent statement, that making 7.7 can take
> > a while yet.
>
> What are your parameters? I've started working on the scripts this
> weekend, and unfortunately for me, I am bursting with ideas of things
> to try out - this is going to be helpful for the future, but not so
> good for the present. I am planning on working on it an hour every day,
> so I should have branching hopefully done soon, and then at least
> pre-release creation done right after that.
>
> To explain a bit the delay, the switch to git is more than just
> changing some configuration-management commands in the script.
> Git opens up the door for doing things a little differently.
> For instance, I will have the scripts sends the email for me,
> instead of me doing some tedious copy/pasting - this is now possible
> because I don't have to be afraid of losing the connection to
> sourceware while creating the branch from a repo on my laptop.
> Same thing for GPG signing.
>
> If the delay is unbearable to your platform, then we'll need to
> temporary re-open the CVS, and produce an extra release from there.
> Or the alternative is to produce a release by hand, but that would
> take much more time, I think. Neither of these 2 options are
> attractive, so it'd be better if we could wait for me to be ready.

The 2.24 release will break debugging of MIPS16 and microMIPS binaries.
Here are 7.6 branch testsuite results for these two ISA variations
respectively:

=== gdb Summary === === gdb Summary ===

# of expected passes 3949 # of expected passes 3949
# of unexpected failures 627 # of unexpected failures 627
# of expected failures 13 # of expected failures 13
# of known failures 14 # of known failures 14
# of unresolved testcases 3852 # of unresolved testcases 3851
# of untested testcases 86 # of untested testcases 86
# of unsupported tests 159 # of unsupported tests 160

Please note that this is a regression compared to binutils 2.23. With the
change below these results turn into these:

=== gdb Summary === === gdb Summary ===

# of expected passes 15890 # of expected passes 15903
# of unexpected failures 241 # of unexpected failures 89
# of unexpected successes 1 # of unexpected successes 1
# of expected failures 28 # of expected failures 28
# of known failures 57 # of known failures 57
# of unresolved testcases 6 # of unresolved testcases 4
# of untested testcases 61 # of untested testcases 61
# of unsupported tests 193 # of unsupported tests 194

I'd prefer we had a GDB release we could refer ordinary people who compile
from sources to if using binutils 2.24 with MIPS16 and microMIPS binaries.
I don't care about distributions, they have the required resources and
experience at hand to port and integrate individual changes if required.
Referring ordinary people to the GIT master head or a snapshot is I think
below the standards the free software community is meant to maintain,
especially for such a core component as GDB.

Although if you expect the delay between binutils 2.24 and GDB 7.7 to
stay within a couple weeks, e.g. if you think you'll be able to roll the
latter out by say mid December, then I think this will be acceptable and
wasting your time you could spend on 7.7 to make this extra release to
satisfy early birds unjustified. I could also use that time to dust off
and resubmit the two outstanding MIPS16/microMIPS changes I already
offered and whose review (of the core non-MIPS parts) went nowhere.

WDYT?

2013-11-21 Maciej W. Rozycki <macro@codesourcery.com>
Paul Brook <paul@codesourcery.com>

bfd/
* elfxx-mips.h (_bfd_mips_elf_get_synthetic_symtab): New
prototype.
* elf32-mips.c (elf_backend_plt_sym_val): Remove macro.
(bfd_elf32_get_synthetic_symtab): New macro.
* elfxx-mips.c (micromips_o32_exec_plt0_entry): New variable.
(micromips_insn32_o32_exec_plt0_entry): Likewise.
(mips16_o32_exec_plt_entry): Likewise.
(micromips_o32_exec_plt_entry): Likewise.
(micromips_insn32_o32_exec_plt_entry): Likewise.
(_bfd_mips_elf_get_synthetic_symtab): New
function.

gdb/
* mips-tdep.c (mips_elf_make_msymbol_special): Handle MIPS16 and
microMIPS synthetic symbols.

opcodes/
* mips-dis.c (is_mips16_plt_tail): New function.
(print_insn_mips16): Handle MIPS16 PLT entry's GOT slot address
word.
(is_compressed_mode_p): Handle MIPS16/microMIPS PLT entries.

Maciej

binutils-umips16-plt-stubs.diff
Index: gdb-fsf-7.6-quilt/bfd/elf32-mips.c
===================================================================
--- gdb-fsf-7.6-quilt.orig/bfd/elf32-mips.c 2013-11-21 03:11:06.147967511 +0000
+++ gdb-fsf-7.6-quilt/bfd/elf32-mips.c 2013-11-21 03:11:13.148736118 +0000
@@ -2344,7 +2344,6 @@ static const struct ecoff_debug_swap mip
#define elf_backend_default_use_rela_p 0
#define elf_backend_sign_extend_vma TRUE
#define elf_backend_plt_readonly 1
-#define elf_backend_plt_sym_val _bfd_mips_elf_plt_sym_val

#define elf_backend_discard_info _bfd_mips_elf_discard_info
#define elf_backend_ignore_discarded_relocs \
@@ -2356,6 +2355,7 @@ static const struct ecoff_debug_swap mip
mips_elf_is_local_label_name
#define bfd_elf32_bfd_is_target_special_symbol \
_bfd_mips_elf_is_target_special_symbol
+#define bfd_elf32_get_synthetic_symtab _bfd_mips_elf_get_synthetic_symtab
#define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line
#define bfd_elf32_find_inliner_info _bfd_mips_elf_find_inliner_info
#define bfd_elf32_new_section_hook _bfd_mips_elf_new_section_hook
@@ -2483,7 +2483,6 @@ mips_vxworks_final_write_processing (bfd
#define elf_backend_default_use_rela_p 1
#undef elf_backend_got_header_size
#define elf_backend_got_header_size (4 * 3)
-#undef elf_backend_plt_sym_val

#undef elf_backend_finish_dynamic_symbol
#define elf_backend_finish_dynamic_symbol \
@@ -2509,4 +2508,6 @@ mips_vxworks_final_write_processing (bfd
#undef elf_backend_symbol_processing
/* NOTE: elf_backend_rela_normal is not defined for MIPS. */

+#undef bfd_elf32_get_synthetic_symtab
+
#include "elf32-target.h"
Index: gdb-fsf-7.6-quilt/bfd/elfxx-mips.c
===================================================================
--- gdb-fsf-7.6-quilt.orig/bfd/elfxx-mips.c 2013-11-21 03:11:06.147967511 +0000
+++ gdb-fsf-7.6-quilt/bfd/elfxx-mips.c 2013-11-21 17:44:05.928757474 +0000
@@ -969,7 +969,40 @@ static const bfd_vma mips_n64_exec_plt0_
0x2718fffe /* subu $24, $24, 2 */
};

-/* The format of subsequent PLT entries. */
+/* The format of the microMIPS first PLT entry in an O32 executable.
+ We rely on v0 ($2) rather than t8 ($24) to contain the address
+ of the GOTPLT entry handled, so this stub may only be used when
+ all the subsequent PLT entries are microMIPS code too.
+
+ The trailing NOP is for alignment and correct disassembly only. */
+static const bfd_vma micromips_o32_exec_plt0_entry[] =
+{
+ 0x7980, 0x0000, /* addiupc $3, (&GOTPLT[0]) - . */
+ 0xff23, 0x0000, /* lw $25, 0($3) */
+ 0x0535, /* subu $2, $2, $3 */
+ 0x2525, /* srl $2, $2, 2 */
+ 0x3302, 0xfffe, /* subu $24, $2, 2 */
+ 0x0dff, /* move $15, $31 */
+ 0x45f9, /* jalrs $25 */
+ 0x0f83, /* move $28, $3 */
+ 0x0c00 /* nop */
+};
+
+/* The format of the microMIPS first PLT entry in an O32 executable
+ in the insn32 mode. */
+static const bfd_vma micromips_insn32_o32_exec_plt0_entry[] =
+{
+ 0x41bc, 0x0000, /* lui $28, %hi(&GOTPLT[0]) */
+ 0xff3c, 0x0000, /* lw $25, %lo(&GOTPLT[0])($28) */
+ 0x339c, 0x0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */
+ 0x0398, 0xc1d0, /* subu $24, $24, $28 */
+ 0x001f, 0x7950, /* move $15, $31 */
+ 0x0318, 0x1040, /* srl $24, $24, 2 */
+ 0x03f9, 0x0f3c, /* jalr $25 */
+ 0x3318, 0xfffe /* subu $24, $24, 2 */
+};
+
+/* The format of subsequent standard PLT entries. */
static const bfd_vma mips_exec_plt_entry[] =
{
0x3c0f0000, /* lui $15, %hi(.got.plt entry) */
@@ -978,6 +1011,39 @@ static const bfd_vma mips_exec_plt_entry
0x03200008 /* jr $25 */
};

+/* The format of subsequent MIPS16 o32 PLT entries. We use v0 ($2)
+ and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not
+ directly addressable. */
+static const bfd_vma mips16_o32_exec_plt_entry[] =
+{
+ 0xb203, /* lw $2, 12($pc) */
+ 0x9a60, /* lw $3, 0($2) */
+ 0x651a, /* move $24, $2 */
+ 0xeb00, /* jr $3 */
+ 0x653b, /* move $25, $3 */
+ 0x6500, /* nop */
+ 0x0000, 0x0000 /* .word (.got.plt entry) */
+};
+
+/* The format of subsequent microMIPS o32 PLT entries. We use v0 ($2)
+ as a temporary because t8 ($24) is not addressable with ADDIUPC. */
+static const bfd_vma micromips_o32_exec_plt_entry[] =
+{
+ 0x7900, 0x0000, /* addiupc $2, (.got.plt entry) - . */
+ 0xff22, 0x0000, /* lw $25, 0($2) */
+ 0x4599, /* jr $25 */
+ 0x0f02 /* move $24, $2 */
+};
+
+/* The format of subsequent microMIPS o32 PLT entries in the insn32 mode. */
+static const bfd_vma micromips_insn32_o32_exec_plt_entry[] =
+{
+ 0x41af, 0x0000, /* lui $15, %hi(.got.plt entry) */
+ 0xff2f, 0x0000, /* lw $25, %lo(.got.plt entry)($15) */
+ 0x0019, 0x0f3c, /* jr $25 */
+ 0x330f, 0x0000 /* addiu $24, $15, %lo(.got.plt entry) */
+};
+
/* The format of the first PLT entry in a VxWorks executable. */
static const bfd_vma mips_vxworks_exec_plt0_entry[] =
{
@@ -14347,6 +14413,246 @@ _bfd_mips_elf_plt_sym_val (bfd_vma i, co
+ i * 4 * ARRAY_SIZE (mips_exec_plt_entry));
}

+/* Build a table of synthetic symbols to represent the PLT. As with MIPS16
+ and microMIPS PLT slots we may have a many-to-one mapping between .plt
+ and .got.plt and also the slots may be of a different size each we walk
+ the PLT manually fetching instructions and matching them against known
+ patterns. To make things easier standard MIPS slots, if any, always come
+ first. As we don't create proper ELF symbols we use the UDATA.I member
+ of ASYMBOL to carry ISA annotation. The encoding used is the same as
+ with the ST_OTHER member of the ELF symbol. */
+
+long
+_bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
+ long symcount ATTRIBUTE_UNUSED,
+ asymbol **syms ATTRIBUTE_UNUSED,
+ long dynsymcount, asymbol **dynsyms,
+ asymbol **ret)
+{
+ static const char pltname[] = "_PROCEDURE_LINKAGE_TABLE_";
+ static const char microsuffix[] = "@micromipsplt";
+ static const char m16suffix[] = "@mips16plt";
+ static const char mipssuffix[] = "@plt";
+
+ bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_boolean micromips_p = MICROMIPS_P (abfd);
+ Elf_Internal_Shdr *hdr;
+ bfd_byte *plt_data;
+ bfd_vma plt_offset;
+ unsigned int other;
+ bfd_vma entry_size;
+ bfd_vma plt0_size;
+ asection *relplt;
+ bfd_vma opcode;
+ asection *plt;
+ asymbol *send;
+ size_t size;
+ char *names;
+ long counti;
+ arelent *p;
+ asymbol *s;
+ char *nend;
+ long count;
+ long pi;
+ long i;
+ long n;
+
+ *ret = NULL;
+
+ if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0 || dynsymcount <= 0)
+ return 0;
+
+ relplt = bfd_get_section_by_name (abfd, ".rel.plt");
+ if (relplt == NULL)
+ return 0;
+
+ hdr = &elf_section_data (relplt)->this_hdr;
+ if (hdr->sh_link != elf_dynsymtab (abfd) || hdr->sh_type != SHT_REL)
+ return 0;
+
+ plt = bfd_get_section_by_name (abfd, ".plt");
+ if (plt == NULL)
+ return 0;
+
+ slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+ if (!(*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
+ return -1;
+ p = relplt->relocation;
+
+ /* Calculating the exact amount of space required for symbols would
+ require two passes over the PLT, so just pessimise assuming two
+ PLT slots per relocation. */
+ count = relplt->size / hdr->sh_entsize;
+ counti = count * bed->s->int_rels_per_ext_rel;
+ size = 2 * count * sizeof (asymbol);
+ size += count * (sizeof (mipssuffix) +
+ (micromips_p ? sizeof (microsuffix) : sizeof (m16suffix)));
+ for (pi = 0; pi < counti; pi += bed->s->int_rels_per_ext_rel)
+ size += 2 * strlen ((*p[pi].sym_ptr_ptr)->name);
+
+ /* Add the size of "_PROCEDURE_LINKAGE_TABLE_" too. */
+ size += sizeof (asymbol) + sizeof (pltname);
+
+ if (!bfd_malloc_and_get_section (abfd, plt, &plt_data))
+ return -1;
+
+ if (plt->size < 16)
+ return -1;
+
+ s = *ret = bfd_malloc (size);
+ if (s == NULL)
+ return -1;
+ send = s + 2 * count + 1;
+
+ names = (char *) send;
+ nend = (char *) s + size;
+ n = 0;
+
+ opcode = bfd_get_micromips_32 (abfd, plt_data + 12);
+ if (opcode == 0x3302fffe)
+ {
+ if (!micromips_p)
+ return -1;
+ plt0_size = 2 * ARRAY_SIZE (micromips_o32_exec_plt0_entry);
+ other = STO_MICROMIPS;
+ }
+ else if (opcode == 0x0398c1d0)
+ {
+ if (!micromips_p)
+ return -1;
+ plt0_size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry);
+ other = STO_MICROMIPS;
+ }
+ else
+ {
+ plt0_size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
+ other = 0;
+ }
+
+ s->the_bfd = abfd;
+ s->flags = BSF_SYNTHETIC | BSF_FUNCTION | BSF_LOCAL;
+ s->section = plt;
+ s->value = 0;
+ s->name = names;
+ s->udata.i = other;
+ memcpy (names, pltname, sizeof (pltname));
+ names += sizeof (pltname);
+ ++s, ++n;
+
+ pi = 0;
+ for (plt_offset = plt0_size;
+ plt_offset + 8 <= plt->size && s < send;
+ plt_offset += entry_size)
+ {
+ bfd_vma gotplt_addr;
+ const char *suffix;
+ bfd_vma gotplt_hi;
+ bfd_vma gotplt_lo;
+ size_t suffixlen;
+
+ opcode = bfd_get_micromips_32 (abfd, plt_data + plt_offset + 4);
+
+ /* Check if the second word matches the expected MIPS16 instruction. */
+ if (opcode == 0x651aeb00)
+ {
+ if (micromips_p)
+ return -1;
+ /* Truncated table??? */
+ if (plt_offset + 16 > plt->size)
+ break;
+ gotplt_addr = bfd_get_32 (abfd, plt_data + plt_offset + 12);
+ entry_size = 2 * ARRAY_SIZE (mips16_o32_exec_plt_entry);
+ suffixlen = sizeof (m16suffix);
+ suffix = m16suffix;
+ other = STO_MIPS16;
+ }
+ /* Likewise the expected microMIPS instruction (no insn32 mode). */
+ else if (opcode == 0xff220000)
+ {
+ if (!micromips_p)
+ return -1;
+ gotplt_hi = bfd_get_16 (abfd, plt_data + plt_offset) & 0x7f;
+ gotplt_lo = bfd_get_16 (abfd, plt_data + plt_offset + 2) & 0xffff;
+ gotplt_hi = ((gotplt_hi ^ 0x40) - 0x40) << 18;
+ gotplt_lo <<= 2;
+ gotplt_addr = gotplt_hi + gotplt_lo;
+ gotplt_addr += ((plt->vma + plt_offset) | 3) ^ 3;
+ entry_size = 2 * ARRAY_SIZE (micromips_o32_exec_plt_entry);
+ suffixlen = sizeof (microsuffix);
+ suffix = microsuffix;
+ other = STO_MICROMIPS;
+ }
+ /* Likewise the expected microMIPS instruction (insn32 mode). */
+ else if ((opcode & 0xffff0000) == 0xff2f0000)
+ {
+ gotplt_hi = bfd_get_16 (abfd, plt_data + plt_offset + 2) & 0xffff;
+ gotplt_lo = bfd_get_16 (abfd, plt_data + plt_offset + 6) & 0xffff;
+ gotplt_hi = ((gotplt_hi ^ 0x8000) - 0x8000) << 16;
+ gotplt_lo = (gotplt_lo ^ 0x8000) - 0x8000;
+ gotplt_addr = gotplt_hi + gotplt_lo;
+ entry_size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt_entry);
+ suffixlen = sizeof (microsuffix);
+ suffix = microsuffix;
+ other = STO_MICROMIPS;
+ }
+ /* Otherwise assume standard MIPS code. */
+ else
+ {
+ gotplt_hi = bfd_get_32 (abfd, plt_data + plt_offset) & 0xffff;
+ gotplt_lo = bfd_get_32 (abfd, plt_data + plt_offset + 4) & 0xffff;
+ gotplt_hi = ((gotplt_hi ^ 0x8000) - 0x8000) << 16;
+ gotplt_lo = (gotplt_lo ^ 0x8000) - 0x8000;
+ gotplt_addr = gotplt_hi + gotplt_lo;
+ entry_size = 4 * ARRAY_SIZE (mips_exec_plt_entry);
+ suffixlen = sizeof (mipssuffix);
+ suffix = mipssuffix;
+ other = 0;
+ }
+ /* Truncated table??? */
+ if (plt_offset + entry_size > plt->size)
+ break;
+
+ for (i = 0;
+ i < count && p[pi].address != gotplt_addr;
+ i++, pi = (pi + bed->s->int_rels_per_ext_rel) % counti);
+
+ if (i < count)
+ {
+ size_t namelen;
+ size_t len;
+
+ *s = **p[pi].sym_ptr_ptr;
+ /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since
+ we are defining a symbol, ensure one of them is set. */
+ if ((s->flags & BSF_LOCAL) == 0)
+ s->flags |= BSF_GLOBAL;
+ s->flags |= BSF_SYNTHETIC;
+ s->section = plt;
+ s->value = plt_offset;
+ s->name = names;
+ s->udata.i = other;
+
+ len = strlen ((*p[pi].sym_ptr_ptr)->name);
+ namelen = len + suffixlen;
+ if (names + namelen > nend)
+ break;
+
+ memcpy (names, (*p[pi].sym_ptr_ptr)->name, len);
+ names += len;
+ memcpy (names, suffix, suffixlen);
+ names += suffixlen;
+
+ ++s, ++n;
+ pi = (pi + bed->s->int_rels_per_ext_rel) % counti;
+ }
+ }
+
+ free (plt_data);
+
+ return n;
+}
+
void
_bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
{
Index: gdb-fsf-7.6-quilt/bfd/elfxx-mips.h
===================================================================
--- gdb-fsf-7.6-quilt.orig/bfd/elfxx-mips.h 2013-11-21 03:11:06.147967511 +0000
+++ gdb-fsf-7.6-quilt/bfd/elfxx-mips.h 2013-11-21 03:11:13.148736118 +0000
@@ -152,6 +152,8 @@ extern bfd_boolean _bfd_mips_elf_init_st
asection *(*) (const char *, asection *, asection *));
extern bfd_vma _bfd_mips_elf_plt_sym_val
(bfd_vma, const asection *, const arelent *rel);
+extern long _bfd_mips_elf_get_synthetic_symtab
+ (bfd *, long, asymbol **, long, asymbol **, asymbol **);
extern void _bfd_mips_post_process_headers
(bfd *abfd, struct bfd_link_info *link_info);

Index: gdb-fsf-7.6-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-7.6-quilt.orig/gdb/mips-tdep.c 2013-11-21 03:11:06.147967511 +0000
+++ gdb-fsf-7.6-quilt/gdb/mips-tdep.c 2013-11-21 17:39:39.367812441 +0000
@@ -343,8 +343,9 @@ make_compact_addr (CORE_ADDR addr)
"special", i.e. refers to a MIPS16 or microMIPS function, and sets
one of the "special" bits in a minimal symbol to mark it accordingly.
The test checks an ELF-private flag that is valid for true function
- symbols only; in particular synthetic symbols such as for PLT stubs
- have no ELF-private part at all.
+ symbols only; for synthetic symbols such as for PLT stubs that have
+ no ELF-private part at all the MIPS BFD backend arranges for this
+ information to be carried in the asymbol's udata field instead.

msymbol_is_mips16 and msymbol_is_micromips test the "special" bit
in a minimal symbol. */
@@ -353,13 +354,18 @@ static void
mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
{
elf_symbol_type *elfsym = (elf_symbol_type *) sym;
+ unsigned char st_other;

- if ((sym->flags & BSF_SYNTHETIC) != 0)
+ if ((sym->flags & BSF_SYNTHETIC) == 0)
+ st_other = elfsym->internal_elf_sym.st_other;
+ else if ((sym->flags & BSF_FUNCTION) != 0)
+ st_other = sym->udata.i;
+ else
return;

- if (ELF_ST_IS_MICROMIPS (elfsym->internal_elf_sym.st_other))
+ if (ELF_ST_IS_MICROMIPS (st_other))
MSYMBOL_TARGET_FLAG_2 (msym) = 1;
- else if (ELF_ST_IS_MIPS16 (elfsym->internal_elf_sym.st_other))
+ else if (ELF_ST_IS_MIPS16 (st_other))
MSYMBOL_TARGET_FLAG_1 (msym) = 1;
}

Index: gdb-fsf-7.6-quilt/opcodes/mips-dis.c
===================================================================
--- gdb-fsf-7.6-quilt.orig/opcodes/mips-dis.c 2013-11-21 03:11:06.147967511 +0000
+++ gdb-fsf-7.6-quilt/opcodes/mips-dis.c 2013-11-21 03:11:13.148736118 +0000
@@ -2033,6 +2033,23 @@ print_mips16_insn_arg (char type,
}
}

+
+/* Check if the given address is the last word of a MIPS16 PLT entry.
+ This word is data and depending on the value it may interfere with
+ disassembly of further PLT entries. We make use of the fact PLT
+ symbols are marked BSF_SYNTHETIC. */
+static bfd_boolean
+is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
+{
+ if (info->symbols
+ && info->symbols[0]
+ && (info->symbols[0]->flags & BSF_SYNTHETIC)
+ && addr == bfd_asymbol_value (info->symbols[0]) + 12)
+ return TRUE;
+
+ return FALSE;
+}
+
/* Disassemble mips16 instructions. */

static int
@@ -2040,7 +2057,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
{
const fprintf_ftype infprintf = info->fprintf_func;
int status;
- bfd_byte buffer[2];
+ bfd_byte buffer[4];
int length;
int insn;
bfd_boolean use_extend;
@@ -2053,11 +2070,32 @@ print_insn_mips16 (bfd_vma memaddr, stru
info->insn_info_valid = 1;
info->branch_delay_insns = 0;
info->data_size = 0;
- info->insn_type = dis_nonbranch;
info->target = 0;
info->target2 = 0;

- status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+ /* Decode PLT entry's GOT slot address word. */
+ if (is_mips16_plt_tail (info, memaddr))
+ {
+ info->insn_type = dis_noninsn;
+ status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+ if (status == 0)
+ {
+ unsigned int gotslot;
+
+ if (info->endian == BFD_ENDIAN_BIG)
+ gotslot = bfd_getb32 (buffer);
+ else
+ gotslot = bfd_getl32 (buffer);
+ infprintf (is, ".word\t0x%x", gotslot);
+
+ return 4;
+ }
+ }
+ else
+ {
+ info->insn_type = dis_nonbranch;
+ status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+ }
if (status != 0)
{
(*info->memory_error_func) (status, memaddr, info);
@@ -2931,27 +2969,26 @@ print_insn_micromips (bfd_vma memaddr, s
static bfd_boolean
is_compressed_mode_p (struct disassemble_info *info)
{
- elf_symbol_type *symbol;
- int pos;
int i;
+ int l;

- for (i = 0; i < info->num_symbols; i++)
- {
- pos = info->symtab_pos + i;
-
- if (bfd_asymbol_flavour (info->symtab[pos]) != bfd_target_elf_flavour)
- continue;
-
- if (info->symtab[pos]->section != info->section)
- continue;
-
- symbol = (elf_symbol_type *) info->symtab[pos];
- if ((!micromips_ase
- && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
- || (micromips_ase
- && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
- return 1;
- }
+ for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
+ if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
+ && ((!micromips_ase
+ && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
+ || (micromips_ase
+ && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
+ return 1;
+ else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
+ && info->symtab[i]->section == info->section)
+ {
+ elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
+ if ((!micromips_ase
+ && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
+ || (micromips_ase
+ && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
+ return 1;
+ }

return 0;
}