[PATCH v2 1/2] ISA bit treatment on the MIPS platform

Maciej W. Rozycki
2014-10-06T00:42:09Z

Joel,

I'd like to get back to this review, this change is important for
reliable debugging compressed code, as test results quoted below indicate.

On Mon, 11 Jun 2012, Joel Brobecker wrote:

> > I propose therefore to accept the existing inconsistencies and deal
> > with them entirely within GDB. I have figured out that the ISA bit
> > lost in various places can still be recovered as long as we have
> > symbol information -- that'll have the st_other attribute correctly
> > set to one of standard MIPS/MIPS16/microMIPS.
>
> That seems reasonable to me.

Great!

> Just some minor comments below:
>
> > gdb-mips16-isa-bit.diff
> > Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
> > ===================================================================
> > --- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c 2012-05-14 16:00:33.000000000 +0100
> > +++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c 2012-05-14 16:02:02.235560558 +0100
> > @@ -358,9 +358,15 @@ mips_elf_make_msymbol_special (asymbol *
> > return;
> >
> > if (ELF_ST_IS_MICROMIPS (elfsym->internal_elf_sym.st_other))
> > - MSYMBOL_TARGET_FLAG_2 (msym) = 1;
> > + {
> > + MSYMBOL_TARGET_FLAG_2 (msym) = 1;
> > + SYMBOL_VALUE_ADDRESS (msym) |= 1;
> > + }
> > else if (ELF_ST_IS_MIPS16 (elfsym->internal_elf_sym.st_other))
> > - MSYMBOL_TARGET_FLAG_1 (msym) = 1;
> > + {
> > + MSYMBOL_TARGET_FLAG_1 (msym) = 1;
> > + SYMBOL_VALUE_ADDRESS (msym) |= 1;
> > + }
>
> This remark is not to be considered as part of this patch's review,
> since this is already an established practice, but I think we could do
> better than using magic numbers for those flags. I understand they have
> to be that way in the common code, but perhaps mips-tdep could define
> aliases? Something like MSYMBOL_MIPS_TARGET_FLAG_BLAH?

Good point, I'll push such a change as a followup; I have it ready now.

> > Index: gdb-fsf-trunk-quilt/gdb/arch-utils.c
> [...]
> > +void
> > +default_make_symbol_special (struct symbol *sym, struct objfile *objfile)
>
> Can you put a comment at the start of all these new functions to say
> that the documentation is in the header file? For instance, I think
> we typically say:
>
> /* See arch-utils.h. */
>
> This is to help someone reviewing the code to know that there is
> in fact documentation.

Done now; please note there's no prior example of such commentary in
arch-utils.c, so it's easy to fall in the trap of following surrounding
code.

> > +/* Do nothing version of make_symbol_special. */
> > +
> > +void default_make_symbol_special (struct symbol *sym, struct objfile *objfile);
> > +
> > +/* Do nothing version of adjust_dwarf2_addr. */
> > +
> > +CORE_ADDR default_adjust_dwarf2_addr (CORE_ADDR pc);
> > +
> > +/* Do nothing version of adjust_dwarf2_line. */
> > +
> > +CORE_ADDR default_adjust_dwarf2_line (CORE_ADDR addr, int rel);
>
> I would definitely mention gdbarch in the function comment.
> Prior art uses:
>
> /* Default implementation of gdbarch_displaced_hw_singlestep. */
>
> Should we remain consistent with that? It can be a mix of both,
> saying what method it implements, and then what it actually does, Eg:
>
> /* Default version of gdbarch_make_symbol_special (does nothing). */

Like above, e.g.:

/* Do nothing version of coff_make_msymbol_special. */

but again I find your suggestion very reasonable. I decided upon wording
like:

/* Do nothing default implementation of gdbarch_make_symbol_special. */

> > Index: gdb-fsf-trunk-quilt/gdb/solib.c
> > ===================================================================
> > --- gdb-fsf-trunk-quilt.orig/gdb/solib.c 2012-05-14 15:56:45.000000000 +0100
> > +++ gdb-fsf-trunk-quilt/gdb/solib.c 2012-05-14 16:01:34.645558637 +0100
> > @@ -1384,8 +1384,27 @@ gdb_bfd_lookup_symbol_from_symtab (bfd *
> >
> > if (match_sym (sym, data))
> > {
> > + symaddr = sym->value;
> > +
> > + /* macro/2012-04-20: Some ELF targets fiddle with addresses
> > + of symbols they consider special. They use minimal symbols
> > + to do that and this is needed for correct breakpoint
> > + placement, but we do not have full data here to build a
> > + complete minimal symbol, so just set the address and let the
> > + targets cope with that. */
> > + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
> > + {
> > + struct minimal_symbol msym;
> > +
> > + memset (&msym, 0, sizeof (msym));
> > + SYMBOL_VALUE_ADDRESS (&msym) = symaddr;
> > + gdbarch_elf_make_msymbol_special (target_gdbarch,
> > + sym, &msym);
> > + symaddr = SYMBOL_VALUE_ADDRESS (&msym);
> > + }
>
> Is there a way we could avoid that block if
> gdbarch_elf_make_msymbol_special points to the default implementation?
> It just seems sad to be doing all this work of creating a temporary symbol
> for every solib symbol on non-mips targets...
>
> One possible way would have been to provide no default value for
> gdbarch_elf_make_msymbol_special, but then it makes the calling
> of that method a little trickier. That could be worked around by
> changing the default value of gdbarch_elf_make_msymbol_special to NULL,
> and then having an extra wrapper function that call the gdbarch
> method if not NULL or else does nothing.

The only other call sites are in `elf_symtab_read' in gdb/elfread.c, so
while I agree the block in gdb/solib.c will best be avoided, I'd call your
proposal to make a wrapper an overkill and actually a pessimisation.

Instead I propose the change I included below, where
`gdbarch_elf_make_msymbol_special_p' is called once per `elf_symtab_read'
invocation only, avoiding all the `gdbarch_elf_make_msymbol_special_p' or
`gdbarch_elf_make_msymbol_special' indirection being called for nothing
where the latter function doesn't do anything. This is actually an
improvement over our current trunk as it is. We can think of something
fancier if a need arises in the future.

Here's an updated change. Beside the changes above I have made an update
to `micromips_linux_sigframe_validate' in gdb/mips-linux-tdep.c, to take
the change to support microMIPS signal frames posted separately into
account. Also I have updated numerous places in gdb/dwarf2read.c so that
the ISA bit is applied to the PC consistently. This cured some
regressions the original change caused, so that there are no regressions
after this change and the test suite fix sent as a complement. Finally a
test case is now also included that covers scenarios this fix addresses;
the test case fails for MIPS16 and microMIPS multilibs with our current
trunk as it is. It is quite possible that the test case will reveal
issues on other targets too.

For those who have already forgotten what it is all about, the original
description is available here:

http://sourceware.org/ml/gdb-patches/2012-05/msg00515.html

I have regression tested this updated version with the mips-linux-gnu
target and the following multilibs:

-EB
-EB -msoft-float
-EB -mips16
-EB -mips16 -msoft-float
-EB -mmicromips
-EB -mmicromips -msoft-float
-EB -mabi=n32
-EB -mabi=n32 -msoft-float
-EB -mabi=64
-EB -mabi=64 -msoft-float

and the -EL variants of same, reducing the total number of failures
counted across all multilibs from ~8500 to ~3750. Numbers are indicative
because of intermittent errors; gdb.threads/schedlock.exp is particularly
notorious with fluctuations in the range of 50 total across all multilibs
being normal. These numbers include fixes made with the other change.

An indicative test summary change for a single multilib, -EB -mmicromips,
before:

=== gdb Summary ===

# of expected passes 16585
# of unexpected failures 1272
# of unexpected successes 1
# of expected failures 29
# of known failures 54
# of unresolved testcases 5
# of untested testcases 50
# of unsupported tests 257

and after:

=== gdb Summary ===

# of expected passes 17717
# of unexpected failures 175
# of unexpected successes 1
# of expected failures 29
# of known failures 56
# of unresolved testcases 5
# of untested testcases 50
# of unsupported tests 268

This change does cause regressions, across all multilibs, in some test
cases that use artificial DWARF-2 records. These include:

gdb.cp/nsalias.exp
gdb.dwarf2/dw2-canonicalize-type.exp
gdb.dwarf2/dw2-empty-pc-range.exp
gdb.dwarf2/pr11465.exp

It also causes regressions across compressed ISA multilibs only in:

gdb.cp/expand-psymtabs-cxx.exp
gdb.dwarf2/dw2-case-insensitive.exp

These tests just make wrong assumptions that can't stand for the MIPS
target, e.g. that a function can be 1-byte long (wrong, the smallest MIPS
instruction takes 2 bytes). The other patch sent as a complement
addresses these issues, which are all test case deficiencies rather than
problems with this change.

OK to apply?

2014-10-06 Maciej W. Rozycki <macro@codesourcery.com>
Maciej W. Rozycki <macro@mips.com>
Pedro Alves <pedro@codesourcery.com>

* gdbarch.sh (elf_make_msymbol_special): Change type to `F',
remove `predefault' and `invalid_p' initializers.
(make_symbol_special): New architecture method.
(adjust_dwarf2_addr, adjust_dwarf2_line): Likewise.
(objfile, symbol): New declarations.
* arch-utils.h (default_elf_make_msymbol_special): Remove
prototype.
(default_make_symbol_special): New prototype.
(default_adjust_dwarf2_addr): Likewise.
(default_adjust_dwarf2_line): Likewise.
* mips-tdep.h (mips_unmake_compact_addr): New prototype.
* arch-utils.c (default_elf_make_msymbol_special): Remove
function.
(default_make_symbol_special): New function.
(default_adjust_dwarf2_addr): Likewise.
(default_adjust_dwarf2_line): Likewise.
* dwarf2-frame.c (decode_frame_entry_1): Call
`gdbarch_adjust_dwarf2_addr'.
* dwarf2loc.c (dwarf2_find_location_expression): Likewise.
* dwarf2read.c (create_addrmap_from_index): Likewise.
(process_psymtab_comp_unit_reader): Likewise.
(add_partial_symbol): Likewise.
(add_partial_subprogram): Likewise.
(process_full_comp_unit): Likewise.
(read_file_scope): Likewise.
(read_func_scope): Likewise. Call `gdbarch_make_symbol_special'.
(read_lexical_block_scope): Call `gdbarch_adjust_dwarf2_addr'.
(read_call_site_scope): Likewise.
(dwarf2_ranges_read): Likewise.
(dwarf2_record_block_ranges): Likewise.
(read_attribute_value): Likewise.
(dwarf_decode_lines_1): Call `gdbarch_adjust_dwarf2_line'.
(new_symbol_full): Call `gdbarch_adjust_dwarf2_addr'.
* elfread.c (elf_symtab_read): Don't call
`gdbarch_elf_make_msymbol_special' if unset.
* mips-linux-tdep.c (micromips_linux_sigframe_validate): Strip
the ISA bit from the PC.
* mips-tdep.c (mips_unmake_compact_addr): New function.
(mips_elf_make_msymbol_special): Set the ISA bit in the symbol's
address appropriately.
(mips_make_symbol_special): New function.
(mips_pc_is_mips): Set the ISA bit before symbol lookup.
(mips_pc_is_mips16): Likewise.
(mips_pc_is_micromips): Likewise.
(mips_pc_isa): Likewise.
(mips_adjust_dwarf2_addr): New function.
(mips_adjust_dwarf2_line): Likewise.
(mips_read_pc, mips_unwind_pc): Keep the ISA bit.
(mips_addr_bits_remove): Likewise.
(mips_skip_trampoline_code): Likewise.
(mips_write_pc): Don't set the ISA bit.
(mips_eabi_push_dummy_call): Likewise.
(mips_o64_push_dummy_call): Likewise.
(mips_gdbarch_init): Install `mips_make_symbol_special',
`mips_adjust_dwarf2_addr' and `mips_adjust_dwarf2_line' gdbarch
handlers.
* solib.c (gdb_bfd_lookup_symbol_from_symtab): Get
target-specific symbol address adjustments.
* gdbarch.h: Regenerate.
* gdbarch.c: Regenerate.

2014-10-06 Maciej W. Rozycki <macro@codesourcery.com>

gdb/testsuite/
* gdb.base/func-ptrs.c: New file.
* gdb.base/func-ptrs.exp: New file.

Maciej

gdb-mips16-isa-bit.diff
Index: gdb-fsf-trunk-quilt/gdb/arch-utils.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/arch-utils.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/arch-utils.c 2014-10-03 14:50:26.000000000 +0100
@@ -31,6 +31,7 @@
#include "target-descriptions.h"
#include "objfiles.h"
#include "language.h"
+#include "symtab.h"

#include "version.h"

@@ -167,17 +168,35 @@ no_op_reg_to_regnum (struct gdbarch *gdb
}

void
-default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
+default_coff_make_msymbol_special (int val, struct minimal_symbol *msym)
{
return;
}

+/* See arch-utils.h. */
+
void
-default_coff_make_msymbol_special (int val, struct minimal_symbol *msym)
+default_make_symbol_special (struct symbol *sym, struct objfile *objfile)
{
return;
}

+/* See arch-utils.h. */
+
+CORE_ADDR
+default_adjust_dwarf2_addr (CORE_ADDR pc)
+{
+ return pc;
+}
+
+/* See arch-utils.h. */
+
+CORE_ADDR
+default_adjust_dwarf2_line (CORE_ADDR addr, int rel)
+{
+ return addr;
+}
+
int
cannot_register_not (struct gdbarch *gdbarch, int regnum)
{
Index: gdb-fsf-trunk-quilt/gdb/arch-utils.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/arch-utils.h 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/arch-utils.h 2014-10-03 14:50:26.000000000 +0100
@@ -68,15 +68,22 @@ extern gdbarch_convert_from_func_ptr_add

extern int no_op_reg_to_regnum (struct gdbarch *gdbarch, int reg);

-/* Do nothing version of elf_make_msymbol_special. */
-
-void default_elf_make_msymbol_special (asymbol *sym,
- struct minimal_symbol *msym);
-
/* Do nothing version of coff_make_msymbol_special. */

void default_coff_make_msymbol_special (int val, struct minimal_symbol *msym);

+/* Do nothing default implementation of gdbarch_make_symbol_special. */
+
+void default_make_symbol_special (struct symbol *sym, struct objfile *objfile);
+
+/* Do nothing default implementation of gdbarch_adjust_dwarf2_addr. */
+
+CORE_ADDR default_adjust_dwarf2_addr (CORE_ADDR pc);
+
+/* Do nothing default implementation of gdbarch_adjust_dwarf2_line. */
+
+CORE_ADDR default_adjust_dwarf2_line (CORE_ADDR addr, int rel);
+
/* Version of cannot_fetch_register() / cannot_store_register() that
always fails. */

Index: gdb-fsf-trunk-quilt/gdb/dwarf2-frame.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/dwarf2-frame.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/dwarf2-frame.c 2014-10-03 14:50:26.398945943 +0100
@@ -2067,6 +2067,7 @@ decode_frame_entry_1 (struct comp_unit *
{
/* This is a FDE. */
struct dwarf2_fde *fde;
+ CORE_ADDR addr;

/* Check that an FDE was expected. */
if ((entry_type & EH_FDE_TYPE_ID) == 0)
@@ -2100,14 +2101,16 @@ decode_frame_entry_1 (struct comp_unit *

gdb_assert (fde->cie != NULL);

- fde->initial_location =
- read_encoded_value (unit, fde->cie->encoding, fde->cie->ptr_size,
- buf, &bytes_read, 0);
+ addr = read_encoded_value (unit, fde->cie->encoding, fde->cie->ptr_size,
+ buf, &bytes_read, 0);
+ fde->initial_location = gdbarch_adjust_dwarf2_addr (gdbarch, addr);
buf += bytes_read;

fde->address_range =
read_encoded_value (unit, fde->cie->encoding & 0x0f,
fde->cie->ptr_size, buf, &bytes_read, 0);
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + fde->address_range);
+ fde->address_range = addr - fde->initial_location;
buf += bytes_read;

/* A 'z' augmentation in the CIE implies the presence of an
Index: gdb-fsf-trunk-quilt/gdb/dwarf2loc.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/dwarf2loc.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/dwarf2loc.c 2014-10-03 14:50:26.398945943 +0100
@@ -4294,6 +4294,9 @@ loclist_describe_location (struct symbol
low += base_address;
high += base_address;

+ low = gdbarch_adjust_dwarf2_addr (gdbarch, low);
+ high = gdbarch_adjust_dwarf2_addr (gdbarch, high);
+
length = extract_unsigned_integer (loc_ptr, 2, byte_order);
loc_ptr += 2;

Index: gdb-fsf-trunk-quilt/gdb/dwarf2read.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/dwarf2read.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/dwarf2read.c 2014-10-06 00:13:56.039006986 +0100
@@ -2824,6 +2824,7 @@ create_signatured_type_table_from_index
static void
create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
const gdb_byte *iter, *end;
struct obstack temp_obstack;
struct addrmap *mutable_map;
@@ -2865,8 +2866,9 @@ create_addrmap_from_index (struct objfil
continue;
}

- addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
- dw2_get_cutu (cu_index));
+ lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr);
+ hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr);
+ addrmap_set_empty (mutable_map, lo, hi - 1, dw2_get_cutu (cu_index));
}

objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
@@ -5848,6 +5850,7 @@ process_psymtab_comp_unit_reader (const
{
struct dwarf2_cu *cu = reader->cu;
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct dwarf2_per_cu_data *per_cu = cu->per_cu;
struct attribute *attr;
CORE_ADDR baseaddr;
@@ -5892,8 +5895,11 @@ process_psymtab_comp_unit_reader (const
/* Store the contiguous range if it is not empty; it can be empty for
CUs with no code. */
addrmap_set_empty (objfile->psymtabs_addrmap,
- best_lowpc + baseaddr,
- best_highpc + baseaddr - 1, pst);
+ gdbarch_adjust_dwarf2_addr (gdbarch,
+ best_lowpc + baseaddr),
+ gdbarch_adjust_dwarf2_addr (gdbarch,
+ best_highpc + baseaddr) - 1,
+ pst);

/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
@@ -5924,8 +5930,8 @@ process_psymtab_comp_unit_reader (const
best_highpc = highpc;
}
}
- pst->textlow = best_lowpc + baseaddr;
- pst->texthigh = best_highpc + baseaddr;
+ pst->textlow = gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr);
+ pst->texthigh = gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr);

pst->n_global_syms = objfile->global_psymbols.next -
(objfile->global_psymbols.list + pst->globals_offset);
@@ -6788,6 +6794,7 @@ static void
add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
CORE_ADDR addr = 0;
const char *actual_name = NULL;
CORE_ADDR baseaddr;
@@ -6805,31 +6812,30 @@ add_partial_symbol (struct partial_die_i
switch (pdi->tag)
{
case DW_TAG_subprogram:
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr);
if (pdi->is_external || cu->language == language_ada)
{
/* brobecker/2007-12-26: Normally, only "external" DIEs are part
of the global scope. But in Ada, we want to be able to access
nested procedures globally. So all Ada subprograms are stored
in the global scope. */
- /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
- mst_text, objfile); */
+ /* prim_record_minimal_symbol (actual_name, addr, mst_text,
+ objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr,
- cu->language, objfile);
+ 0, addr, cu->language, objfile);
}
else
{
- /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
- mst_file_text, objfile); */
+ /* prim_record_minimal_symbol (actual_name, addr, mst_file_text,
+ objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr,
- cu->language, objfile);
+ 0, addr, cu->language, objfile);
}
break;
case DW_TAG_constant:
@@ -7020,6 +7026,9 @@ add_partial_subprogram (struct partial_d
CORE_ADDR *lowpc, CORE_ADDR *highpc,
int set_addrmap, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
if (pdi->tag == DW_TAG_subprogram)
{
if (pdi->has_pc_info)
@@ -7030,14 +7039,18 @@ add_partial_subprogram (struct partial_d
*highpc = pdi->highpc;
if (set_addrmap)
{
- CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
+ CORE_ADDR baseaddr;
+ CORE_ADDR highpc;
+ CORE_ADDR lowpc;

baseaddr = ANOFFSET (objfile->section_offsets,
SECT_OFF_TEXT (objfile));
- addrmap_set_empty (objfile->psymtabs_addrmap,
- pdi->lowpc + baseaddr,
- pdi->highpc - 1 + baseaddr,
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ pdi->lowpc + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ pdi->highpc + baseaddr);
+ addrmap_set_empty (objfile->psymtabs_addrmap, lowpc, highpc - 1,
cu->per_cu->v.psymtab);
}
}
@@ -7921,11 +7934,13 @@ process_full_comp_unit (struct dwarf2_pe
{
struct dwarf2_cu *cu = per_cu->cu;
struct objfile *objfile = per_cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
CORE_ADDR lowpc, highpc;
struct symtab *symtab;
struct cleanup *back_to, *delayed_list_cleanup;
CORE_ADDR baseaddr;
struct block *static_block;
+ CORE_ADDR addr;

baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));

@@ -7956,8 +7971,8 @@ process_full_comp_unit (struct dwarf2_pe
it, by scanning the DIE's below the compilation unit. */
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);

- static_block
- = end_symtab_get_static_block (highpc + baseaddr, objfile, 0, 1);
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
+ static_block = end_symtab_get_static_block (addr, objfile, 0, 1);

/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
@@ -9001,6 +9016,7 @@ static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct cleanup *back_to = make_cleanup (null_cleanup, 0);
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
@@ -9019,8 +9035,7 @@ read_file_scope (struct die_info *die, s
from finish_block. */
if (lowpc == ((CORE_ADDR) -1))
lowpc = highpc;
- lowpc += baseaddr;
- highpc += baseaddr;
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);

find_file_and_directory (die, cu, &name, &comp_dir);

@@ -11131,6 +11146,7 @@ static void
read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct context_stack *new;
CORE_ADDR lowpc;
CORE_ADDR highpc;
@@ -11183,8 +11199,8 @@ read_func_scope (struct die_info *die, s
return;
}

- lowpc += baseaddr;
- highpc += baseaddr;
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);

/* If we have any template arguments, then we must allocate a
different sort of symbol. */
@@ -11271,6 +11287,8 @@ read_func_scope (struct die_info *die, s
/* If we have address ranges, record them. */
dwarf2_record_block_ranges (die, block, baseaddr, cu);

+ gdbarch_make_symbol_special (gdbarch, new->name, objfile);
+
/* Attach template arguments to function. */
if (! VEC_empty (symbolp, template_args))
{
@@ -11307,6 +11325,7 @@ static void
read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct context_stack *new;
CORE_ADDR lowpc, highpc;
struct die_info *child_die;
@@ -11321,8 +11340,8 @@ read_lexical_block_scope (struct die_inf
describe ranges. */
if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
return;
- lowpc += baseaddr;
- highpc += baseaddr;
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);

push_context (0, lowpc);
if (die->child != NULL)
@@ -11384,6 +11403,7 @@ read_call_site_scope (struct die_info *d
return;
}
pc = attr_value_as_address (attr) + baseaddr;
+ pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc);

if (cu->call_site_htab == NULL)
cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
@@ -11532,7 +11552,10 @@ read_call_site_scope (struct die_info *d
"low pc, for referencing DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
else
- SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr);
+ {
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
+ SET_FIELD_PHYSADDR (call_site->target, lowpc);
+ }
}
}
else
@@ -11660,6 +11683,7 @@ dwarf2_ranges_read (unsigned offset, COR
struct partial_symtab *ranges_pst)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct comp_unit_head *cu_header = &cu->header;
bfd *obfd = objfile->obfd;
unsigned int addr_size = cu_header->addr_size;
@@ -11767,10 +11791,17 @@ dwarf2_ranges_read (unsigned offset, COR
}

if (ranges_pst != NULL)
- addrmap_set_empty (objfile->psymtabs_addrmap,
- range_beginning + baseaddr,
- range_end - 1 + baseaddr,
- ranges_pst);
+ {
+ CORE_ADDR lowpc;
+ CORE_ADDR highpc;
+
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ range_beginning + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ range_end + baseaddr);
+ addrmap_set_empty (objfile->psymtabs_addrmap, lowpc, highpc - 1,
+ ranges_pst);
+ }

/* FIXME: This is recording everything as a low-high
segment of consecutive addresses. We should have a
@@ -11984,6 +12015,7 @@ dwarf2_record_block_ranges (struct die_i
CORE_ADDR baseaddr, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct attribute *attr;
struct attribute *attr_high;

@@ -11999,7 +12031,9 @@ dwarf2_record_block_ranges (struct die_i
if (cu->header.version >= 4 && attr_form_is_constant (attr_high))
high += low;

- record_block_range (block, baseaddr + low, baseaddr + high - 1);
+ low = gdbarch_adjust_dwarf2_addr (gdbarch, low + baseaddr);
+ high = gdbarch_adjust_dwarf2_addr (gdbarch, high + baseaddr);
+ record_block_range (block, low, high - 1);
}
}

@@ -12103,6 +12137,8 @@ dwarf2_record_block_ranges (struct die_i
continue;
}

+ start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
+ end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
record_block_range (block, start, end - 1);
}
}
@@ -15926,6 +15962,8 @@ read_attribute_value (const struct die_r
const gdb_byte *info_ptr)
{
struct dwarf2_cu *cu = reader->cu;
+ struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
bfd *abfd = reader->abfd;
struct comp_unit_head *cu_header = &cu->header;
unsigned int bytes_read;
@@ -15948,6 +15986,7 @@ read_attribute_value (const struct die_r
break;
case DW_FORM_addr:
DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+ DW_ADDR (attr) = gdbarch_adjust_dwarf2_addr (gdbarch, DW_ADDR (attr));
info_ptr += bytes_read;
break;
case DW_FORM_block2:
@@ -17278,7 +17317,7 @@ dwarf_decode_lines_1 (struct line_header
while (line_ptr < line_end)
{
/* state machine registers */
- CORE_ADDR address = 0;
+ CORE_ADDR address = gdbarch_adjust_dwarf2_line (gdbarch, 0, 0);
unsigned int file = 1;
unsigned int line = 1;
int is_stmt = lh->default_is_stmt;
@@ -17321,12 +17360,14 @@ dwarf_decode_lines_1 (struct line_header
{
/* Special opcode. */
unsigned char adj_opcode;
+ CORE_ADDR addr_adj;
int line_delta;

adj_opcode = op_code - lh->opcode_base;
- address += (((op_index + (adj_opcode / lh->line_range))
+ addr_adj = (((op_index + (adj_opcode / lh->line_range))
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
+ address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
op_index = ((op_index + (adj_opcode / lh->line_range))
% lh->maximum_ops_per_instruction);
line_delta = lh->line_base + (adj_opcode % lh->line_range);
@@ -17403,6 +17444,7 @@ dwarf_decode_lines_1 (struct line_header
op_index = 0;
line_ptr += bytes_read;
address += baseaddr;
+ address = gdbarch_adjust_dwarf2_line (gdbarch, address, 0);
break;
case DW_LNE_define_file:
{
@@ -17480,10 +17522,12 @@ dwarf_decode_lines_1 (struct line_header
{
CORE_ADDR adjust
= read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ CORE_ADDR addr_adj;

- address += (((op_index + adjust)
+ addr_adj = (((op_index + adjust)
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
+ address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
op_index = ((op_index + adjust)
% lh->maximum_ops_per_instruction);
line_ptr += bytes_read;
@@ -17543,18 +17587,25 @@ dwarf_decode_lines_1 (struct line_header
case DW_LNS_const_add_pc:
{
CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
+ CORE_ADDR addr_adj;

- address += (((op_index + adjust)
+ addr_adj = (((op_index + adjust)
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
+ address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
op_index = ((op_index + adjust)
% lh->maximum_ops_per_instruction);
}
break;
case DW_LNS_fixed_advance_pc:
- address += read_2_bytes (abfd, line_ptr);
- op_index = 0;
- line_ptr += 2;
+ {
+ CORE_ADDR addr_adj;
+
+ addr_adj = read_2_bytes (abfd, line_ptr);
+ address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ op_index = 0;
+ line_ptr += 2;
+ }
break;
default:
{
@@ -17811,6 +17862,7 @@ new_symbol_full (struct die_info *die, s
struct symbol *space)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct symbol *sym = NULL;
const char *name;
struct attribute *attr = NULL;
@@ -17888,8 +17940,13 @@ new_symbol_full (struct die_info *die, s
case DW_TAG_label:
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
- SYMBOL_VALUE_ADDRESS (sym)
- = attr_value_as_address (attr) + baseaddr;
+ {
+ CORE_ADDR addr;
+
+ addr = attr_value_as_address (attr);
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr);
+ SYMBOL_VALUE_ADDRESS (sym) = addr;
+ }
SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
Index: gdb-fsf-trunk-quilt/gdb/elfread.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/elfread.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/elfread.c 2014-10-03 14:50:26.398945943 +0100
@@ -247,6 +247,8 @@ elf_symtab_read (struct objfile *objfile
const char *filesymname = "";
struct dbx_symfile_info *dbx = DBX_SYMFILE_INFO (objfile);
int stripped = (bfd_get_symcount (objfile->obfd) == 0);
+ int elf_make_msymbol_special_p
+ = gdbarch_elf_make_msymbol_special_p (gdbarch);

for (i = 0; i < number_of_symbols; i++)
{
@@ -330,7 +332,8 @@ elf_symtab_read (struct objfile *objfile
if (msym != NULL)
{
msym->filename = filesymname;
- gdbarch_elf_make_msymbol_special (gdbarch, sym, msym);
+ if (elf_make_msymbol_special_p)
+ gdbarch_elf_make_msymbol_special (gdbarch, sym, msym);
}
continue;
}
@@ -558,7 +561,8 @@ elf_symtab_read (struct objfile *objfile
}

msym->filename = filesymname;
- gdbarch_elf_make_msymbol_special (gdbarch, sym, msym);
+ if (elf_make_msymbol_special_p)
+ gdbarch_elf_make_msymbol_special (gdbarch, sym, msym);
}

/* If we see a default versioned symbol, install it under
@@ -597,7 +601,9 @@ elf_symtab_read (struct objfile *objfile
SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym));
mtramp->created_by_gdb = 1;
mtramp->filename = filesymname;
- gdbarch_elf_make_msymbol_special (gdbarch, sym, mtramp);
+ if (elf_make_msymbol_special_p)
+ gdbarch_elf_make_msymbol_special (gdbarch,
+ sym, mtramp);
}
}
}
Index: gdb-fsf-trunk-quilt/gdb/gdbarch.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbarch.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/gdbarch.c 2014-10-03 14:50:26.000000000 +0100
@@ -252,6 +252,9 @@ struct gdbarch
gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p;
gdbarch_elf_make_msymbol_special_ftype *elf_make_msymbol_special;
gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special;
+ gdbarch_make_symbol_special_ftype *make_symbol_special;
+ gdbarch_adjust_dwarf2_addr_ftype *adjust_dwarf2_addr;
+ gdbarch_adjust_dwarf2_line_ftype *adjust_dwarf2_line;
int cannot_step_breakpoint;
int have_nonsteppable_watchpoint;
gdbarch_address_class_type_flags_ftype *address_class_type_flags;
@@ -390,8 +393,10 @@ gdbarch_alloc (const struct gdbarch_info
gdbarch->skip_solib_resolver = generic_skip_solib_resolver;
gdbarch->in_solib_return_trampoline = generic_in_solib_return_trampoline;
gdbarch->in_function_epilogue_p = generic_in_function_epilogue_p;
- gdbarch->elf_make_msymbol_special = default_elf_make_msymbol_special;
gdbarch->coff_make_msymbol_special = default_coff_make_msymbol_special;
+ gdbarch->make_symbol_special = default_make_symbol_special;
+ gdbarch->adjust_dwarf2_addr = default_adjust_dwarf2_addr;
+ gdbarch->adjust_dwarf2_line = default_adjust_dwarf2_line;
gdbarch->register_reggroup_p = default_register_reggroup_p;
gdbarch->displaced_step_hw_singlestep = default_displaced_step_hw_singlestep;
gdbarch->displaced_step_fixup = NULL;
@@ -561,8 +566,11 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of skip_solib_resolver, invalid_p == 0 */
/* Skip verify of in_solib_return_trampoline, invalid_p == 0 */
/* Skip verify of in_function_epilogue_p, invalid_p == 0 */
- /* Skip verify of elf_make_msymbol_special, invalid_p == 0 */
+ /* Skip verify of elf_make_msymbol_special, has predicate. */
/* Skip verify of coff_make_msymbol_special, invalid_p == 0 */
+ /* Skip verify of make_symbol_special, invalid_p == 0 */
+ /* Skip verify of adjust_dwarf2_addr, invalid_p == 0 */
+ /* Skip verify of adjust_dwarf2_line, invalid_p == 0 */
/* Skip verify of cannot_step_breakpoint, invalid_p == 0 */
/* Skip verify of have_nonsteppable_watchpoint, invalid_p == 0 */
/* Skip verify of address_class_type_flags, has predicate. */
@@ -684,6 +692,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: adjust_breakpoint_address = <%s>\n",
host_address_to_string (gdbarch->adjust_breakpoint_address));
fprintf_unfiltered (file,
+ "gdbarch_dump: adjust_dwarf2_addr = <%s>\n",
+ host_address_to_string (gdbarch->adjust_dwarf2_addr));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: adjust_dwarf2_line = <%s>\n",
+ host_address_to_string (gdbarch->adjust_dwarf2_line));
+ fprintf_unfiltered (file,
"gdbarch_dump: auto_charset = <%s>\n",
host_address_to_string (gdbarch->auto_charset));
fprintf_unfiltered (file,
@@ -834,6 +848,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: ecoff_reg_to_regnum = <%s>\n",
host_address_to_string (gdbarch->ecoff_reg_to_regnum));
fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_elf_make_msymbol_special_p() = %d\n",
+ gdbarch_elf_make_msymbol_special_p (gdbarch));
+ fprintf_unfiltered (file,
"gdbarch_dump: elf_make_msymbol_special = <%s>\n",
host_address_to_string (gdbarch->elf_make_msymbol_special));
fprintf_unfiltered (file,
@@ -1008,6 +1025,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: make_corefile_notes = <%s>\n",
host_address_to_string (gdbarch->make_corefile_notes));
fprintf_unfiltered (file,
+ "gdbarch_dump: make_symbol_special = <%s>\n",
+ host_address_to_string (gdbarch->make_symbol_special));
+ fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_max_insn_length_p() = %d\n",
gdbarch_max_insn_length_p (gdbarch));
fprintf_unfiltered (file,
@@ -3055,6 +3075,13 @@ set_gdbarch_in_function_epilogue_p (stru
gdbarch->in_function_epilogue_p = in_function_epilogue_p;
}

+int
+gdbarch_elf_make_msymbol_special_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->elf_make_msymbol_special != NULL;
+}
+
void
gdbarch_elf_make_msymbol_special (struct gdbarch *gdbarch, asymbol *sym, struct minimal_symbol *msym)
{
@@ -3089,6 +3116,57 @@ set_gdbarch_coff_make_msymbol_special (s
gdbarch->coff_make_msymbol_special = coff_make_msymbol_special;
}

+void
+gdbarch_make_symbol_special (struct gdbarch *gdbarch, struct symbol *sym, struct objfile *objfile)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->make_symbol_special != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_make_symbol_special called\n");
+ gdbarch->make_symbol_special (sym, objfile);
+}
+
+void
+set_gdbarch_make_symbol_special (struct gdbarch *gdbarch,
+ gdbarch_make_symbol_special_ftype make_symbol_special)
+{
+ gdbarch->make_symbol_special = make_symbol_special;
+}
+
+CORE_ADDR
+gdbarch_adjust_dwarf2_addr (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->adjust_dwarf2_addr != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_adjust_dwarf2_addr called\n");
+ return gdbarch->adjust_dwarf2_addr (pc);
+}
+
+void
+set_gdbarch_adjust_dwarf2_addr (struct gdbarch *gdbarch,
+ gdbarch_adjust_dwarf2_addr_ftype adjust_dwarf2_addr)
+{
+ gdbarch->adjust_dwarf2_addr = adjust_dwarf2_addr;
+}
+
+CORE_ADDR
+gdbarch_adjust_dwarf2_line (struct gdbarch *gdbarch, CORE_ADDR addr, int rel)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->adjust_dwarf2_line != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_adjust_dwarf2_line called\n");
+ return gdbarch->adjust_dwarf2_line (addr, rel);
+}
+
+void
+set_gdbarch_adjust_dwarf2_line (struct gdbarch *gdbarch,
+ gdbarch_adjust_dwarf2_line_ftype adjust_dwarf2_line)
+{
+ gdbarch->adjust_dwarf2_line = adjust_dwarf2_line;
+}
+
int
gdbarch_cannot_step_breakpoint (struct gdbarch *gdbarch)
{
Index: gdb-fsf-trunk-quilt/gdb/gdbarch.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbarch.h 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/gdbarch.h 2014-10-03 14:50:26.000000000 +0100
@@ -51,6 +51,8 @@ struct target_ops;
struct obstack;
struct bp_target_info;
struct target_desc;
+struct objfile;
+struct symbol;
struct displaced_step_closure;
struct core_regset_section;
struct syscall;
@@ -682,6 +684,8 @@ typedef int (gdbarch_in_function_epilogu
extern int gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR addr);
extern void set_gdbarch_in_function_epilogue_p (struct gdbarch *gdbarch, gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p);

+extern int gdbarch_elf_make_msymbol_special_p (struct gdbarch *gdbarch);
+
typedef void (gdbarch_elf_make_msymbol_special_ftype) (asymbol *sym, struct minimal_symbol *msym);
extern void gdbarch_elf_make_msymbol_special (struct gdbarch *gdbarch, asymbol *sym, struct minimal_symbol *msym);
extern void set_gdbarch_elf_make_msymbol_special (struct gdbarch *gdbarch, gdbarch_elf_make_msymbol_special_ftype *elf_make_msymbol_special);
@@ -690,6 +694,18 @@ typedef void (gdbarch_coff_make_msymbol_
extern void gdbarch_coff_make_msymbol_special (struct gdbarch *gdbarch, int val, struct minimal_symbol *msym);
extern void set_gdbarch_coff_make_msymbol_special (struct gdbarch *gdbarch, gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special);

+typedef void (gdbarch_make_symbol_special_ftype) (struct symbol *sym, struct objfile *objfile);
+extern void gdbarch_make_symbol_special (struct gdbarch *gdbarch, struct symbol *sym, struct objfile *objfile);
+extern void set_gdbarch_make_symbol_special (struct gdbarch *gdbarch, gdbarch_make_symbol_special_ftype *make_symbol_special);
+
+typedef CORE_ADDR (gdbarch_adjust_dwarf2_addr_ftype) (CORE_ADDR pc);
+extern CORE_ADDR gdbarch_adjust_dwarf2_addr (struct gdbarch *gdbarch, CORE_ADDR pc);
+extern void set_gdbarch_adjust_dwarf2_addr (struct gdbarch *gdbarch, gdbarch_adjust_dwarf2_addr_ftype *adjust_dwarf2_addr);
+
+typedef CORE_ADDR (gdbarch_adjust_dwarf2_line_ftype) (CORE_ADDR addr, int rel);
+extern CORE_ADDR gdbarch_adjust_dwarf2_line (struct gdbarch *gdbarch, CORE_ADDR addr, int rel);
+extern void set_gdbarch_adjust_dwarf2_line (struct gdbarch *gdbarch, gdbarch_adjust_dwarf2_line_ftype *adjust_dwarf2_line);
+
extern int gdbarch_cannot_step_breakpoint (struct gdbarch *gdbarch);
extern void set_gdbarch_cannot_step_breakpoint (struct gdbarch *gdbarch, int cannot_step_breakpoint);

Index: gdb-fsf-trunk-quilt/gdb/gdbarch.sh
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbarch.sh 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/gdbarch.sh 2014-10-03 14:50:26.000000000 +0100
@@ -635,8 +635,11 @@ m:int:in_solib_return_trampoline:CORE_AD
# which don't suffer from that problem could just let this functionality
# untouched.
m:int:in_function_epilogue_p:CORE_ADDR addr:addr:0:generic_in_function_epilogue_p::0
-f:void:elf_make_msymbol_special:asymbol *sym, struct minimal_symbol *msym:sym, msym::default_elf_make_msymbol_special::0
+F:void:elf_make_msymbol_special:asymbol *sym, struct minimal_symbol *msym:sym, msym
f:void:coff_make_msymbol_special:int val, struct minimal_symbol *msym:val, msym::default_coff_make_msymbol_special::0
+f:void:make_symbol_special:struct symbol *sym, struct objfile *objfile:sym, objfile::default_make_symbol_special::0
+f:CORE_ADDR:adjust_dwarf2_addr:CORE_ADDR pc:pc::default_adjust_dwarf2_addr::0
+f:CORE_ADDR:adjust_dwarf2_line:CORE_ADDR addr, int rel:addr, rel::default_adjust_dwarf2_line::0
v:int:cannot_step_breakpoint:::0:0::0
v:int:have_nonsteppable_watchpoint:::0:0::0
F:int:address_class_type_flags:int byte_size, int dwarf2_addr_class:byte_size, dwarf2_addr_class
@@ -1140,6 +1143,8 @@ struct target_ops;
struct obstack;
struct bp_target_info;
struct target_desc;
+struct objfile;
+struct symbol;
struct displaced_step_closure;
struct core_regset_section;
struct syscall;
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c 2014-10-03 14:50:26.398945943 +0100
@@ -1372,7 +1372,13 @@ micromips_linux_sigframe_validate (const
struct frame_info *this_frame,
CORE_ADDR *pc)
{
- return mips_pc_is_micromips (get_frame_arch (this_frame), *pc);
+ if (mips_pc_is_micromips (get_frame_arch (this_frame), *pc))
+ {
+ *pc = mips_unmake_compact_addr (*pc);
+ return 1;
+ }
+ else
+ return 0;
}

/* Implement the "write_pc" gdbarch method. */
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c 2014-10-06 00:11:55.028611249 +0100
@@ -333,6 +333,15 @@ make_compact_addr (CORE_ADDR addr)
return ((addr) | (CORE_ADDR) 1);
}

+/* Extern version of unmake_compact_addr; we use a separate function
+ so that unmake_compact_addr can be inlined throughout this file. */
+
+CORE_ADDR
+mips_unmake_compact_addr (CORE_ADDR addr)
+{
+ return unmake_compact_addr (addr);
+}
+
/* Functions for setting and testing a bit in a minimal symbol that
marks it as MIPS16 or microMIPS function. The MSB of the minimal
symbol's "info" field is used for this purpose.
@@ -362,9 +371,15 @@ mips_elf_make_msymbol_special (asymbol *
return;

if (ELF_ST_IS_MICROMIPS (st_other))
- MSYMBOL_TARGET_FLAG_2 (msym) = 1;
+ {
+ MSYMBOL_TARGET_FLAG_2 (msym) = 1;
+ SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1);
+ }
else if (ELF_ST_IS_MIPS16 (st_other))
- MSYMBOL_TARGET_FLAG_1 (msym) = 1;
+ {
+ MSYMBOL_TARGET_FLAG_1 (msym) = 1;
+ SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1);
+ }
}

/* Return one iff MSYM refers to standard ISA code. */
@@ -391,6 +406,29 @@ msymbol_is_micromips (struct minimal_sym
return MSYMBOL_TARGET_FLAG_2 (msym);
}

+/* Set the ISA bit in the main symbol too, complementing the corresponding
+ minimal symbol setting and reflecting the run-time value of the symbol. */
+
+static void
+mips_make_symbol_special (struct symbol *sym, struct objfile *objfile)
+{
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ CORE_ADDR compact_block_start;
+ struct bound_minimal_symbol msym;
+
+ compact_block_start = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) | 1;
+ msym = lookup_minimal_symbol_by_pc (compact_block_start);
+ if (msym.minsym && !msymbol_is_mips (msym.minsym))
+ {
+ /* We are in symbol reading so it is OK to cast away constness. */
+ struct block *block = (struct block *) SYMBOL_BLOCK_VALUE (sym);
+
+ BLOCK_START (block) = compact_block_start;
+ }
+ }
+}
+
/* XFER a value from the big/little/left end of the register.
Depending on the size of the value it might occupy the entire
register or just part of it. Make an allowance for this, aligning
@@ -1125,7 +1163,7 @@ mips_pc_is_mips (CORE_ADDR memaddr)
stored by elfread.c in the high bit of the info field. Use this
to decide if the function is standard MIPS. Otherwise if bit 0
of the address is clear, then this is a standard MIPS function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips (sym.minsym);
else
@@ -1143,7 +1181,7 @@ mips_pc_is_mips16 (struct gdbarch *gdbar
elfread.c in the high bit of the info field. Use this to decide
if the function is MIPS16. Otherwise if bit 0 of the address is
set, then ELF file flags will tell if this is a MIPS16 function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips16 (sym.minsym);
else
@@ -1162,7 +1200,7 @@ mips_pc_is_micromips (struct gdbarch *gd
if the function is microMIPS. Otherwise if bit 0 of the address
is set, then ELF file flags will tell if this is a microMIPS
function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_micromips (sym.minsym);
else
@@ -1182,7 +1220,7 @@ mips_pc_isa (struct gdbarch *gdbarch, CO
this to decide if the function is MIPS16 or microMIPS or normal
MIPS. Otherwise if bit 0 of the address is set, then ELF file
flags will tell if this is a MIPS16 or a microMIPS function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
{
if (msymbol_is_micromips (sym.minsym))
@@ -1203,6 +1241,32 @@ mips_pc_isa (struct gdbarch *gdbarch, CO
}
}

+/* Set the ISA bit correctly in the PC, used by DWARF-2 machinery. */
+
+static CORE_ADDR
+mips_adjust_dwarf2_addr (CORE_ADDR pc)
+{
+ pc = unmake_compact_addr (pc);
+ return mips_pc_is_mips (pc) ? pc : make_compact_addr (pc);
+}
+
+/* Recalculate the line record requested so that the resulting PC has the
+ ISA bit set correctly, used by DWARF-2 machinery. */
+
+static CORE_ADDR
+mips_adjust_dwarf2_line (CORE_ADDR addr, int rel)
+{
+ static CORE_ADDR adj_pc;
+ static CORE_ADDR pc;
+ CORE_ADDR isa_pc;
+
+ pc = rel ? pc + addr : addr;
+ isa_pc = mips_adjust_dwarf2_addr (pc);
+ addr = rel ? isa_pc - adj_pc : isa_pc;
+ adj_pc = isa_pc;
+ return addr;
+}
+
/* Various MIPS16 thunk (aka stub or trampoline) names. */

static const char mips_str_mips16_call_stub[] = "__mips16_call_stub_";
@@ -1252,8 +1316,6 @@ mips_read_pc (struct regcache *regcache)
LONGEST pc;

regcache_cooked_read_signed (regcache, regnum, &pc);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
return pc;
}

@@ -1263,8 +1325,6 @@ mips_unwind_pc (struct gdbarch *gdbarch,
CORE_ADDR pc;

pc = frame_unwind_register_signed (next_frame, gdbarch_pc_regnum (gdbarch));
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
/* macro/2012-04-20: This hack skips over MIPS16 call thunks as
intermediate frames. In this case we can get the caller's address
from $ra, or if $ra contains an address within a thunk as well, then
@@ -1274,15 +1334,9 @@ mips_unwind_pc (struct gdbarch *gdbarch,
{
pc = frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
if (mips_in_frame_stub (pc))
- {
- pc = frame_unwind_register_signed
- (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = frame_unwind_register_signed
+ (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
}
return pc;
}
@@ -1316,10 +1370,7 @@ mips_write_pc (struct regcache *regcache
{
int regnum = gdbarch_pc_regnum (get_regcache_arch (regcache));

- if (mips_pc_is_mips (pc))
- regcache_cooked_write_unsigned (regcache, regnum, pc);
- else
- regcache_cooked_write_unsigned (regcache, regnum, make_compact_addr (pc));
+ regcache_cooked_write_unsigned (regcache, regnum, pc);
}

/* Fetch and return instruction from the specified location. Handle
@@ -3650,9 +3701,6 @@ mips_addr_bits_remove (struct gdbarch *g
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

- if (is_compact_addr (addr))
- addr = unmake_compact_addr (addr);
-
if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
/* This hack is a work-around for existing boards using PMON, the
simulator, and any other 64-bit targets that doesn't have true
@@ -4351,25 +4399,9 @@ mips_eabi_push_dummy_call (struct gdbarc
"mips_eabi_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);

- /* Function pointer arguments to mips16 code need to be made into
- mips16 pointers. */
- if (typecode == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
- {
- CORE_ADDR addr = extract_signed_integer (value_contents (arg),
- len, byte_order);
- if (mips_pc_is_mips (addr))
- val = value_contents (arg);
- else
- {
- store_signed_integer (valbuf, len, byte_order,
- make_compact_addr (addr));
- val = valbuf;
- }
- }
/* The EABI passes structures that do not fit in a register by
reference. */
- else if (len > regsize
+ if (len > regsize
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_unsigned_integer (valbuf, regsize, byte_order,
@@ -5734,7 +5766,6 @@ mips_o64_push_dummy_call (struct gdbarch
for (argnum = 0; argnum < nargs; argnum++)
{
const gdb_byte *val;
- gdb_byte valbuf[MAX_REGISTER_SIZE];
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
@@ -5747,21 +5778,6 @@ mips_o64_push_dummy_call (struct gdbarch

val = value_contents (arg);

- /* Function pointer arguments to mips16 code need to be made into
- mips16 pointers. */
- if (typecode == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
- {
- CORE_ADDR addr = extract_signed_integer (value_contents (arg),
- len, byte_order);
- if (!mips_pc_is_mips (addr))
- {
- store_signed_integer (valbuf, len, byte_order,
- make_compact_addr (addr));
- val = valbuf;
- }
- }
-
/* Floating point arguments passed in registers have to be
treated specially. On 32-bit architectures, doubles are
passed in register pairs; the even FP register gets the
@@ -7678,27 +7694,15 @@ mips_skip_trampoline_code (struct frame_

new_pc = mips_skip_mips16_trampoline_code (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;

new_pc = find_solib_trampoline_target (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;

new_pc = mips_skip_pic_trampoline_code (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
}
while (pc != target_pc);

@@ -8354,6 +8358,9 @@ mips_gdbarch_init (struct gdbarch_info i

set_gdbarch_elf_make_msymbol_special (gdbarch,
mips_elf_make_msymbol_special);
+ set_gdbarch_make_symbol_special (gdbarch, mips_make_symbol_special);
+ set_gdbarch_adjust_dwarf2_addr (gdbarch, mips_adjust_dwarf2_addr);
+ set_gdbarch_adjust_dwarf2_line (gdbarch, mips_adjust_dwarf2_line);

regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum);
*regnum = mips_regnum;
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.h 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.h 2014-10-05 23:03:19.088958183 +0100
@@ -155,6 +155,9 @@ enum
/* Single step based on where the current instruction will take us. */
extern int mips_software_single_step (struct frame_info *frame);

+/* Strip the ISA (compression) bit off from ADDR. */
+extern CORE_ADDR mips_unmake_compact_addr (CORE_ADDR addr);
+
/* Tell if the program counter value in MEMADDR is in a standard
MIPS function. */
extern int mips_pc_is_mips (bfd_vma memaddr);
Index: gdb-fsf-trunk-quilt/gdb/solib.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/solib.c 2014-10-03 13:52:46.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/solib.c 2014-10-03 14:50:26.398945943 +0100
@@ -1444,8 +1444,28 @@ gdb_bfd_lookup_symbol_from_symtab (bfd *

if (match_sym (sym, data))
{
+ struct gdbarch *gdbarch = target_gdbarch ();
+ symaddr = sym->value;
+
+ /* Some ELF targets fiddle with addresses of symbols they
+ consider special. They use minimal symbols to do that
+ and this is needed for correct breakpoint placement,
+ but we do not have full data here to build a complete
+ minimal symbol, so just set the address and let the
+ targets cope with that. */
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && gdbarch_elf_make_msymbol_special_p (gdbarch))
+ {
+ struct minimal_symbol msym;
+
+ memset (&msym, 0, sizeof (msym));
+ SET_MSYMBOL_VALUE_ADDRESS (&msym, symaddr);
+ gdbarch_elf_make_msymbol_special (gdbarch, sym, &msym);
+ symaddr = MSYMBOL_VALUE_RAW_ADDRESS (&msym);
+ }
+
/* BFD symbols are section relative. */
- symaddr = sym->value + sym->section->vma;
+ symaddr += sym->section->vma;
break;
}
}
Index: gdb-fsf-trunk-quilt/gdb/testsuite/gdb.base/func-ptrs.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/testsuite/gdb.base/func-ptrs.c 2014-10-03 14:50:26.398945943 +0100
@@ -0,0 +1,50 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+void
+sentinel (void)
+{
+ return;
+}
+
+int
+incr (int i)
+{
+ sentinel ();
+ return i + 1;
+}
+
+int
+decr (int i)
+{
+ sentinel ();
+ return i - 1;
+}
+
+int (*calc) (int) = incr;
+
+int
+main (void)
+{
+ int i = -1;
+
+ i = calc (i);
+ i = calc (i);
+ i = calc (i);
+
+ return i;
+}
Index: gdb-fsf-trunk-quilt/gdb/testsuite/gdb.base/func-ptrs.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/testsuite/gdb.base/func-ptrs.exp 2014-10-03 14:50:26.398945943 +0100
@@ -0,0 +1,95 @@
+# Copyright 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set testname func-ptrs
+set srcfile ${testname}.c
+if { [prepare_for_testing ${testname}.exp ${testname} ${srcfile}] } {
+ return -1
+}
+
+if { ![runto_main] } {
+ untested ${testname}.exp
+ return -1
+}
+
+
+# First set our breakpoints.
+
+set fp_breakpoint_re \
+ "Breakpoint $decimal at $hex: file .*${srcfile}, line $decimal\\."
+gdb_test "break sentinel if calc == decr" \
+ "${fp_breakpoint_re}" \
+ "breakpoint at sentinel"
+gdb_test "break incr" \
+ "${fp_breakpoint_re}" \
+ "breakpoint at incr"
+gdb_test "break decr" \
+ "${fp_breakpoint_re}" \
+ "breakpoint at decr"
+
+
+# Check if we run through to the breakpoint in incr.
+
+gdb_test "continue" \
+ "Breakpoint $decimal, incr \\(i=-1\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*" \
+ "continue to incr, first time"
+
+
+# Go back up, make sure the return value is 0.
+
+gdb_test "finish" \
+ "Run till exit from #0 +incr \\(i=-1\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+($hex in )?main \\(\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*Value returned is \\$$decimal = 0" \
+ "go back to main from incr, first time"
+
+
+# Redirect calc and see if we run to the breakpoint in decr instead.
+
+gdb_test_no_output "set calc = decr" "set calc to decr"
+gdb_test "continue" \
+ "Breakpoint $decimal, decr \\(i=0\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*" \
+ "continue to decr"
+
+
+# Go back up, check if we stop in sentinel instead.
+
+gdb_test "finish" \
+ "Run till exit from #0 +decr \\(i=0\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+Breakpoint $decimal, sentinel \\(\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*" \
+ "stop in sentinel"
+
+
+# Go back all the way up to main, make sure the return value is -1.
+
+gdb_test_no_output "up-silently" "move up to decr"
+gdb_test "finish" \
+ "Run till exit from #1 +($hex in )?decr \\(i=0\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+($hex in )?main \\(\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*Value returned is \\$$decimal = -1" \
+ "go back to main from decr"
+
+
+# Reset calc and see if we run to the breakpoint in incr again.
+
+gdb_test_no_output "set calc = incr" "set calc to incr"
+gdb_test "continue" \
+ "Breakpoint $decimal, incr \\(i=-1\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*" \
+ "continue to incr, second time"
+
+
+# Go back up again, make sure the return value is 0.
+
+gdb_test "finish" \
+ "Run till exit from #0 +incr \\(i=-1\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+($hex in )?main \\(\\)\[ \r\n\]+at .*${srcfile}:$decimal\[\r\n\]+.*Value returned is \\$$decimal = 0" \
+ "go back to main from incr, second time"
+
+
+# All done!