Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
@ 2010-02-11 11:57 Jan Kratochvil
  2010-02-11 12:13 ` Andreas Schwab
  2010-02-11 12:51 ` Mark Kettenis
  0 siblings, 2 replies; 9+ messages in thread
From: Jan Kratochvil @ 2010-02-11 11:57 UTC (permalink / raw)
  To: binutils; +Cc: gdb-patches

Hi,

CORE_ADDR can be 64bit while gdb (bfd) can handle 32bit inferiors (either when
gdb host is e.g. x86_64 or when --enable-64-bit-bfd is in use).  Currently gdb
(bfd) leaves garbage at the bits 32..63 and clear it only at the last moment
when required (such as when calling ptrace or printing it to the user).

There has been a conclusion gdb (bfd) should rather keep the bits cleared (so
that for example addr1 == addr2 is easily possible):

http://sourceware.org/ml/gdb-patches/2010-01/msg00497.html
# Wouldn't it be more natural to force a canonical representation at
# the time the address is *determined* in the first place?
http://sourceware.org/ml/gdb-patches/2006-09/msg00197.html
# If we have garbage in the high bits, that's a problem already.

Asking if bfd will follow this policy; otherwise the result from
bfd_elf_bfd_from_remote_memory can be also only masked in gdb/.

I had to fixup gdb/ as currently it worked thanksfully due to bfd/ returning
the right magic bits 32..63.
(gdb) p/x loadbase
$1 = 0xffffffff0033b000
(There will follow a gdb/-only patch to handle 64->32 more systematically.)

No regressions on {x86_64,i686}-fedora12-linux-gnu for binutils.  But binutils
itself does not call bfd_from_remote_memory at all.  No regressions on
{x86_64,x86_64-m32,i686}-fedora12-linux-gnu for gdb with the gdb/ part.


bfd/
2010-02-11  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Clear unused bits 32..63 for ELFCLASS32.
	* elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): New variable vaddr,
	use it for target_read_memory.
	(NAME(_bfd_elf,bfd_from_remote_memory) <ELFCLASS == ELFCLASS32>): New.

gdb/
2010-02-11  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* symfile-mem.c: (symbol_file_add_from_memory): New variable addr_bit.
	Mask sai->other[i].addr with it.

--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1745,6 +1745,8 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	  if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
 	    {
 	      loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
+	      if (ELFCLASS == ELFCLASS32)
+		loadbase &= 0xffffffff;
 	      loadbase_set = TRUE;
 	    }
 
@@ -1789,11 +1791,13 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align;
 	bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
 		       + i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
+	bfd_vma vaddr = (i_phdrs[i].p_vaddr + loadbase) & -i_phdrs[i].p_align;
+
+	if (ELFCLASS == ELFCLASS32)
+	  vaddr &= 0xffffffff;
 	if (end > (bfd_vma) contents_size)
 	  end = contents_size;
-	err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr)
-				  & -i_phdrs[i].p_align,
-				  contents + start, end - start);
+	err = target_read_memory (vaddr, contents + start, end - start);
 	if (err)
 	  {
 	    free (x_phdrs);
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -72,6 +73,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
   bfd_vma loadbase;
   struct section_addr_info *sai;
   unsigned int i;
+  int addr_bit = gdbarch_addr_bit (target_gdbarch);
 
   if (bfd_get_flavour (templ) != bfd_target_elf_flavour)
     error (_("add-symbol-file-from-memory not supported for this target"));
@@ -103,6 +105,9 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
 	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
+	if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
+	  sai->other[i].addr &= ((ULONGEST) 1 << addr_bit) - 1;
+
 	sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec);
 	sai->other[i].sectindex = sec->index;
 	++i;


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
  2010-02-11 11:57 [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff Jan Kratochvil
@ 2010-02-11 12:13 ` Andreas Schwab
  2010-02-11 12:43   ` Jan Kratochvil
       [not found]   ` <20100211124302.GA8435__38068.0548646071$1265892205$gmane$org@host0.dyn.jankratochvil.net>
  2010-02-11 12:51 ` Mark Kettenis
  1 sibling, 2 replies; 9+ messages in thread
From: Andreas Schwab @ 2010-02-11 12:13 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: binutils, gdb-patches

Jan Kratochvil <jan.kratochvil@redhat.com> writes:

> --- a/bfd/elfcode.h
> +++ b/bfd/elfcode.h
> @@ -1745,6 +1745,8 @@ NAME(_bfd_elf,bfd_from_remote_memory)
>  	  if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
>  	    {
>  	      loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
> +	      if (ELFCLASS == ELFCLASS32)
> +		loadbase &= 0xffffffff;

Some targets use signed addresses.

Andreas.

-- 
Andreas Schwab, schwab@redhat.com
GPG Key fingerprint = D4E8 DBE3 3813 BB5D FA84  5EC7 45C6 250E 6F00 984E
"And now for something completely different."


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
  2010-02-11 12:13 ` Andreas Schwab
@ 2010-02-11 12:43   ` Jan Kratochvil
       [not found]   ` <20100211124302.GA8435__38068.0548646071$1265892205$gmane$org@host0.dyn.jankratochvil.net>
  1 sibling, 0 replies; 9+ messages in thread
From: Jan Kratochvil @ 2010-02-11 12:43 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: binutils, gdb-patches

On Thu, 11 Feb 2010 13:13:43 +0100, Andreas Schwab wrote:
> Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> 
> > --- a/bfd/elfcode.h
> > +++ b/bfd/elfcode.h
> > @@ -1745,6 +1745,8 @@ NAME(_bfd_elf,bfd_from_remote_memory)
> >  	  if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
> >  	    {
> >  	      loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
> > +	      if (ELFCLASS == ELFCLASS32)
> > +		loadbase &= 0xffffffff;
> 
> Some targets use signed addresses.

http://sourceware.org/ml/gdb-patches/2006-09/msg00197.html
# One caveat:
# if addresses are supposed to be sign extended, we should not print out
# 64-bit addresses for a 32-bit target just because they're sign
# extended.  This will show up on MIPS, which sign extends addresses.

Thanks for bringing up this larger issue.

As this representation is only internal to gdb (bfd) I chose rather to use
always the unsigned/zeroed format as it makes its internal handling in tools
IMO easier.  It does not (or at least does not have to) affect any inferior-
or user- visible behavior.  If someone casts CORE_ADDR -> LONGEST/ULONGEST
then CORE_ADDR should be extended the proper sign/unsigned way from its target
width (such as 32->64).

This patch is a prerequisite for PIE support on 64bit gdb -> 32bit inferior,
commented by Ulrich Weigand in:
http://sourceware.org/ml/gdb-patches/2010-01/msg00497.html

The full gdb patch (not yet posted) already does explicit handling of target
width on any CORE_ADDR in use as an address _displacement_ by ensuring
a compilation error otherwise:

+/* Wrap CORE_ADDR so that normal math operation are no longer valid on it.  Use
+   the set of functions around addr_add_offset to access it.  Direct access to
+   A is permitted for reading A and setting A to constant like zero or one.  */
+typedef struct
+  {
+    CORE_ADDR a;
+  }
+addr_offset_t;

There should be similar part done for all the CORE_ADDR operations to properly
respect target address width.  This is currently already broken anyway.
Therefore if we either always-zero-extend or target-wise-sign-extend CORE_ADDR
should not be a regression.  I do not intend to post such full CORE_ADDR fixup
(outside of the biarch-PIE functionality) in a near future, though.

It may be simpler if CORE_ADDR would be a C++ class with overriden operators.
But moving GDB over to C++ has been currently turned down.


Thanks,
Jan


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
  2010-02-11 11:57 [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff Jan Kratochvil
  2010-02-11 12:13 ` Andreas Schwab
@ 2010-02-11 12:51 ` Mark Kettenis
  2010-02-11 13:30   ` [cancelled] " Jan Kratochvil
  1 sibling, 1 reply; 9+ messages in thread
From: Mark Kettenis @ 2010-02-11 12:51 UTC (permalink / raw)
  To: jan.kratochvil; +Cc: binutils, gdb-patches

> Date: Thu, 11 Feb 2010 12:57:30 +0100
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> 
> Hi,
> 
> CORE_ADDR can be 64bit while gdb (bfd) can handle 32bit inferiors
> (either when gdb host is e.g. x86_64 or when --enable-64-bit-bfd is
> in use).  Currently gdb (bfd) leaves garbage at the bits 32..63 and
> clear it only at the last moment when required (such as when calling
> ptrace or printing it to the user).

Please define "garbage".  I suspect that what you really mean is that
BFD currently returns sign-extended addresses in some cases.  I'll
assume that's what you really mean in the remainder of this reply.

> There has been a conclusion gdb (bfd) should rather keep the bits cleared (so
> that for example addr1 == addr2 is easily possible):
> 
> http://sourceware.org/ml/gdb-patches/2010-01/msg00497.html
> # Wouldn't it be more natural to force a canonical representation at
> # the time the address is *determined* in the first place?

The question is what this canonical representation should be.  It's
not obvious that the solution you propose (clearing the high bits) is
the right one.  Especiallly when you do arithmetic on addresses, sign
extension may actually be the proper thing to do.

> http://sourceware.org/ml/gdb-patches/2006-09/msg00197.html
> # If we have garbage in the high bits, that's a problem already.

Yup, if the high bits are really garbage.

> Asking if bfd will follow this policy; otherwise the result from
> bfd_elf_bfd_from_remote_memory can be also only masked in gdb/.

Is bfd_elf_bfd_from_remote_memory really the only place in BFD that
returns a sign-extended address?

> I had to fixup gdb/ as currently it worked thanksfully due to bfd/ returning
> the right magic bits 32..63.
> (gdb) p/x loadbase
> $1 = 0xffffffff0033b000
> (There will follow a gdb/-only patch to handle 64->32 more systematically.)

Essentially you'll have to make sure all arithmetic on addresses is
done modulo 2^n with n being the number of bits in the address space.

> --- a/gdb/symfile-mem.c
> +++ b/gdb/symfile-mem.c
> @@ -72,6 +73,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
>    bfd_vma loadbase;
>    struct section_addr_info *sai;
>    unsigned int i;
> +  int addr_bit = gdbarch_addr_bit (target_gdbarch);
>  
>    if (bfd_get_flavour (templ) != bfd_target_elf_flavour)
>      error (_("add-symbol-file-from-memory not supported for this target"));
> @@ -103,6 +105,9 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
>      if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
>        {
>  	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
> +	if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
> +	  sai->other[i].addr &= ((ULONGEST) 1 << addr_bit) - 1;
> +
>  	sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec);
>  	sai->other[i].sectindex = sec->index;
>  	++i;

I'm somewhat worried about this change.  Does this mean that on x86
Linux executables get loaded at an address that is high enough that we
section address basically wrap around?

Also, if we go this route, I bet you'll be adding code like this to a
lot of functions.  It may be better to introduce a function that
returns the mask directly, say gdbarch_addr_mask() and use that
unconditionally, like:

  	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
 +	sai->other[i].addr &= gdbarch_addr_mask(gdbarch);

Cheers,

Mark


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [cancelled] Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit  &= 0xffffffff
  2010-02-11 12:51 ` Mark Kettenis
@ 2010-02-11 13:30   ` Jan Kratochvil
  0 siblings, 0 replies; 9+ messages in thread
From: Jan Kratochvil @ 2010-02-11 13:30 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: binutils, gdb-patches

Hi,

cancelling this patch review request.


On Thu, 11 Feb 2010 13:50:52 +0100, Mark Kettenis wrote:
> Please define "garbage".  I suspect that what you really mean is that
> BFD currently returns sign-extended addresses in some cases.

I meant garbage (bits with arbitrary unknown content).

But as I see now fixing few GDB places to always sign-extend the displacement
CORE_ADDR will permit using the current standard 64bit math operators even for
32bit inferiors.  And I can even drop the whole prepared 200KB GDB patch.


> > --- a/gdb/symfile-mem.c
> > +++ b/gdb/symfile-mem.c
> > @@ -72,6 +73,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
> >    bfd_vma loadbase;
> >    struct section_addr_info *sai;
> >    unsigned int i;
> > +  int addr_bit = gdbarch_addr_bit (target_gdbarch);
> >  
> >    if (bfd_get_flavour (templ) != bfd_target_elf_flavour)
> >      error (_("add-symbol-file-from-memory not supported for this target"));
> > @@ -103,6 +105,9 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
> >      if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
> >        {
> >  	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
> > +	if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
> > +	  sai->other[i].addr &= ((ULONGEST) 1 << addr_bit) - 1;
> > +
> >  	sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec);
> >  	sai->other[i].sectindex = sec->index;
> >  	++i;
> 
> I'm somewhat worried about this change.  Does this mean that on x86
> Linux executables get loaded at an address that is high enough that we
> section address basically wrap around?

In fact always: As 32bit vDSO is built for (non-randomized) address 0xffffe000
but it gets placed thanks to the randomization on random VMA space:
00d36000-00d37000 r-xp 00000000 00:00 0     [vdso]


> Also, if we go this route, I bet you'll be adding code like this to a
> lot of functions.  It may be better to introduce a function that
> returns the mask directly, say gdbarch_addr_mask() and use that
> unconditionally, like:
> 
>   	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
>  +	sai->other[i].addr &= gdbarch_addr_mask(gdbarch);

This patch followed the current GDB way of doing it.  My prepared but
hopefully obsoleted now patch was using specifically:
  sai->other[i].addr = addr_add_offset (gdbarch, sai->other[i].addr, loadbase);


Thanks,
Jan


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
       [not found]   ` <20100211124302.GA8435__38068.0548646071$1265892205$gmane$org@host0.dyn.jankratochvil.net>
@ 2010-02-16 23:24     ` Tom Tromey
  2010-02-17 11:34       ` Jan Kratochvil
  0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2010-02-16 23:24 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

Jan> +typedef struct
Jan> +  {
Jan> +    CORE_ADDR a;
Jan> +  }
Jan> +addr_offset_t;

I like this idea.  It is slightly less convenient, but also lets us
control the operations more tightly.

Math on an addr_offset_t would seem to depend on the current target (or
address space).  This is a little gross ... but still it seems like a
decent step.

It seems like you could just call the struct CORE_ADDR.

I am curious to hear what others think of this.

Jan> But as I see now fixing few GDB places to always sign-extend the
Jan> displacement CORE_ADDR will permit using the current standard 64bit
Jan> math operators even for 32bit inferiors.

Maybe I am being fuzzy today, but I don't follow the logic of this
statement.  Is this just because we don't expect "too much" overflow?
Is it impossible for overflow to accumulate in a CORE_ADDR?

Tom


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
  2010-02-16 23:24     ` Tom Tromey
@ 2010-02-17 11:34       ` Jan Kratochvil
  2010-02-17 18:50         ` Tom Tromey
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Kratochvil @ 2010-02-17 11:34 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Wed, 17 Feb 2010 00:24:01 +0100, Tom Tromey wrote:
> Jan> +typedef struct
> Jan> +  {
> Jan> +    CORE_ADDR a;
> Jan> +  }
> Jan> +addr_offset_t;
[...]
> It seems like you could just call the struct CORE_ADDR.

I thought it would be good to have different type for _address_ vs. for
_displacement_.  With this difference some math operations are no longer
valid and I have discovered for example:

displacement used as address: invalid but used in read_type_unit_scope; it
                              should get some cleanup (not investigated more).

valid operations:
address + displacement: valid
address - address used as displacement: valid
displacement + displacement: valid for PIC/PIE offset of section start address.
                             but these are two difference displacements,
                             arbitrary adding of displacements is forbidden.
                             Maybe there should have been distinct types
                             section_displacement and objfile_displacement.
displacement - displacement: valid for delta in objfile_relocate

Anyway with
	[patch] Fix PIE for 64bit gdb -> 32bit inferior
	http://sourceware.org/ml/gdb-patches/2010-02/msg00289.html

this patch will no longer be included (attached just FYI).


> Jan> But as I see now fixing few GDB places to always sign-extend the
> Jan> displacement CORE_ADDR will permit using the current standard 64bit
> Jan> math operators even for 32bit inferiors.
> 
> Maybe I am being fuzzy today, but I don't follow the logic of this
> statement.  Is this just because we don't expect "too much" overflow?
> Is it impossible for overflow to accumulate in a CORE_ADDR?

In general "displacement + displacement" operation is invalid and thus it
cannot overflow.


Thanks,
Jan


--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1745,6 +1745,8 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	  if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
 	    {
 	      loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
+	      if (ELFCLASS == ELFCLASS32)
+		loadbase &= 0xffffffff;
 	      loadbase_set = TRUE;
 	    }
 
@@ -1789,11 +1791,13 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align;
 	bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
 		       + i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
+	bfd_vma vaddr = (i_phdrs[i].p_vaddr + loadbase) & -i_phdrs[i].p_align;
+
+	if (ELFCLASS == ELFCLASS32)
+	  vaddr &= 0xffffffff;
 	if (end > (bfd_vma) contents_size)
 	  end = contents_size;
-	err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr)
-				  & -i_phdrs[i].p_align,
-				  contents + start, end - start);
+	err = target_read_memory (vaddr, contents + start, end - start);
 	if (err)
 	  {
 	    free (x_phdrs);
--- a/gdb/addrmap.c
+++ b/gdb/addrmap.c
@@ -25,6 +25,7 @@
 #include "gdb_obstack.h"
 #include "addrmap.h"
 #include "gdb_assert.h"
+#include "symtab.h"
 
 
 \f
@@ -40,13 +41,15 @@ struct addrmap_funcs
   void *(*find) (struct addrmap *this, CORE_ADDR addr);
   struct addrmap *(*create_fixed) (struct addrmap *this,
                                    struct obstack *obstack);
-  void (*relocate) (struct addrmap *this, CORE_ADDR offset);
+  void (*relocate) (struct addrmap *this, addr_offset_t offset);
 };
 
 
 struct addrmap
 {
   const struct addrmap_funcs *funcs;
+
+  struct gdbarch *gdbarch;
 };
 
 
@@ -76,7 +79,7 @@ addrmap_create_fixed (struct addrmap *original, struct obstack *obstack)
 /* Relocate all the addresses in MAP by OFFSET.  (This can be applied
    to either mutable or immutable maps.)  */
 void
-addrmap_relocate (struct addrmap *map, CORE_ADDR offset)
+addrmap_relocate (struct addrmap *map, addr_offset_t offset)
 {
   map->funcs->relocate (map, offset);
 }
@@ -165,13 +168,15 @@ addrmap_fixed_create_fixed (struct addrmap *this, struct obstack *obstack)
 
 
 static void
-addrmap_fixed_relocate (struct addrmap *this, CORE_ADDR offset)
+addrmap_fixed_relocate (struct addrmap *this, addr_offset_t offset)
 {
   struct addrmap_fixed *map = (struct addrmap_fixed *) this;
   size_t i;
 
   for (i = 0; i < map->num_transitions; i++)
-    map->transitions[i].addr += offset;
+    map->transitions[i].addr = addr_add_offset (this->gdbarch,
+						map->transitions[i].addr,
+						offset);
 }
 
 
@@ -201,7 +206,7 @@ struct addrmap_mutable
      fixed maps, we have no entry at (CORE_ADDR) 0; it doesn't 
      simplify enough.)
 
-     The last region is assumed to end at CORE_ADDR_MAX.
+     The last region is assumed to end at ADDR_MINUS_ONE (the maximal one).
 
      Since we can't know whether CORE_ADDR is larger or smaller than
      splay_tree_key (unsigned long) --- I think both are possible,
@@ -330,7 +335,7 @@ addrmap_mutable_set_empty (struct addrmap *this,
 
   /* Establish transitions at the start and end.  */
   force_transition (map, start);
-  if (end_inclusive < CORE_ADDR_MAX)
+  if (end_inclusive < addr_minus_one (this->gdbarch))
     force_transition (map, end_inclusive + 1);
 
   /* Walk the area, changing all NULL regions to OBJ.  */
@@ -348,7 +353,7 @@ addrmap_mutable_set_empty (struct addrmap *this,
   n = addrmap_splay_tree_predecessor (map, start);
   prior_value = n ? addrmap_node_value (n) : NULL;
   for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n);
-       n && (end_inclusive == CORE_ADDR_MAX
+       n && (end_inclusive == addr_minus_one (this->gdbarch)
              || addrmap_node_key (n) <= end_inclusive + 1);
        n = next)
     {
@@ -419,6 +424,7 @@ addrmap_mutable_create_fixed (struct addrmap *this, struct obstack *obstack)
                           + (num_transitions
                              * sizeof (fixed->transitions[0]))));
   fixed->addrmap.funcs = &addrmap_fixed_funcs;
+  fixed->addrmap.gdbarch = this->gdbarch;
   fixed->num_transitions = 1;
   fixed->transitions[0].addr = 0;
   fixed->transitions[0].value = NULL;
@@ -435,7 +441,7 @@ addrmap_mutable_create_fixed (struct addrmap *this, struct obstack *obstack)
 
 
 static void
-addrmap_mutable_relocate (struct addrmap *this, CORE_ADDR offset)
+addrmap_mutable_relocate (struct addrmap *this, addr_offset_t offset)
 {
   /* Not needed yet.  */
   internal_error (__FILE__, __LINE__,
@@ -507,11 +513,12 @@ splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
 
 
 struct addrmap *
-addrmap_create_mutable (struct obstack *obstack)
+addrmap_create_mutable (struct gdbarch *gdbarch, struct obstack *obstack)
 {
   struct addrmap_mutable *map = obstack_alloc (obstack, sizeof (*map));
 
   map->addrmap.funcs = &addrmap_mutable_funcs;
+  map->addrmap.gdbarch = gdbarch;
   map->obstack = obstack;
 
   /* splay_tree_new_with_allocator uses the provided allocation
--- a/gdb/addrmap.h
+++ b/gdb/addrmap.h
@@ -36,7 +36,8 @@ struct addrmap;
 
 /* Create a mutable address map which maps every address to NULL.
    Allocate entries in OBSTACK.  */
-struct addrmap *addrmap_create_mutable (struct obstack *obstack);
+struct addrmap *addrmap_create_mutable (struct gdbarch *gdbarch,
+					struct obstack *obstack);
 
 /* In the mutable address map MAP, associate the addresses from START
    to END_INCLUSIVE that are currently associated with NULL with OBJ
@@ -89,6 +90,6 @@ struct addrmap *addrmap_create_fixed (struct addrmap *original,
 
 /* Relocate all the addresses in MAP by OFFSET.  (This can be applied
    to either mutable or immutable maps.)  */
-void addrmap_relocate (struct addrmap *map, CORE_ADDR offset);
+void addrmap_relocate (struct addrmap *map, addr_offset_t offset);
 
 #endif /* ADDRMAP_H */
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7530,6 +7530,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
   struct symtabs_and_lines sals;
   struct symtab_and_line sal;
   struct frame_info *frame = get_selected_frame (NULL);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   struct breakpoint *breakpoint;
   struct breakpoint *breakpoint2 = NULL;
   struct cleanup *old_chain;
@@ -7585,7 +7586,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
       make_cleanup_delete_breakpoint (breakpoint2);
     }
 
-  proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+  proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
 
   /* If we are running asynchronously, and proceed call above has actually
      managed to start the target, arrange for breakpoints to be
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -432,7 +432,7 @@ record_pending_block (struct objfile *objfile, struct block *block,
    already provided by BLOCK_START and BLOCK_END, then we create an
    address map for the block.  */
 void
-record_block_range (struct block *block,
+record_block_range (struct gdbarch *gdbarch, struct block *block,
                     CORE_ADDR start, CORE_ADDR end_inclusive)
 {
   /* If this is any different from the range recorded in the block's
@@ -447,7 +447,8 @@ record_block_range (struct block *block,
   if (! pending_addrmap)
     {
       obstack_init (&pending_addrmap_obstack);
-      pending_addrmap = addrmap_create_mutable (&pending_addrmap_obstack);
+      pending_addrmap = addrmap_create_mutable (gdbarch,
+						&pending_addrmap_obstack);
     }
 
   addrmap_set_empty (pending_addrmap, start, end_inclusive, block);
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -248,7 +248,7 @@ extern struct block *finish_block (struct symbol *symbol,
                                    CORE_ADDR start, CORE_ADDR end,
                                    struct objfile *objfile);
 
-extern void record_block_range (struct block *,
+extern void record_block_range (struct gdbarch *gdbarch, struct block *,
                                 CORE_ADDR start, CORE_ADDR end_inclusive);
 
 extern void really_free_pendings (void *dummy);
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -430,7 +430,7 @@ add_dump_command (char *name, void (*func) (char *args, char *mode),
 
 /* Opaque data for restore_section_callback. */
 struct callback_data {
-  CORE_ADDR load_offset;
+  addr_offset_t load_offset;
   CORE_ADDR load_start;
   CORE_ADDR load_end;
 };
@@ -489,19 +489,24 @@ restore_section_callback (bfd *ibfd, asection *isec, void *args)
 		   (unsigned long) sec_start, 
 		   (unsigned long) sec_end);
 
-  if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
+  if (data->load_offset.a != 0 || data->load_start != 0 || data->load_end != 0)
     printf_filtered (" into memory (%s to %s)\n",
 		     paddress (target_gdbarch,
-			       (unsigned long) sec_start
-			       + sec_offset + data->load_offset), 
+			       addr_add_offset (target_gdbarch,
+						sec_start + sec_offset,
+						data->load_offset)),
 		     paddress (target_gdbarch,
-			       (unsigned long) sec_start + sec_offset
-				+ data->load_offset + sec_load_count));
+			       addr_add_offset (target_gdbarch,
+						(sec_start + sec_offset
+						 + sec_load_count),
+						data->load_offset)));
   else
     puts_filtered ("\n");
 
   /* Write the data.  */
-  ret = target_write_memory (sec_start + sec_offset + data->load_offset, 
+  ret = target_write_memory (addr_add_offset (target_gdbarch,
+					      sec_start + sec_offset,
+					      data->load_offset),
 			     buf + sec_offset, sec_load_count);
   if (ret != 0)
     warning (_("restore: memory write failed (%s)."), safe_strerror (ret));
@@ -535,10 +540,14 @@ restore_binary_file (char *filename, struct callback_data *data)
     len -= data->load_start;
 
   printf_filtered 
-    ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n", 
+    ("Restoring binary file %s into memory (%s to %s)\n", 
      filename, 
-     (unsigned long) (data->load_start + data->load_offset),
-     (unsigned long) (data->load_start + data->load_offset + len));
+     paddress (target_gdbarch, addr_add_offset (target_gdbarch,
+						data->load_start,
+						data->load_offset)),
+     paddress (target_gdbarch, addr_add_offset (target_gdbarch,
+						data->load_start + len,
+						data->load_offset)));
 
   /* Now set the file pos to the requested load start pos.  */
   if (fseek (file, data->load_start, SEEK_SET) != 0)
@@ -551,7 +560,9 @@ restore_binary_file (char *filename, struct callback_data *data)
     perror_with_name (filename);
 
   /* Now write the buffer into target memory. */
-  len = target_write_memory (data->load_start + data->load_offset, buf, len);
+  len = target_write_memory (addr_add_offset (target_gdbarch, data->load_start,
+					      data->load_offset),
+			     buf, len);
   if (len != 0)
     warning (_("restore: memory write failed (%s)."), safe_strerror (len));
   return;
@@ -568,9 +579,9 @@ restore_command (char *args, int from_tty)
   if (!target_has_execution)
     noprocess ();
 
-  data.load_offset = 0;
-  data.load_start  = 0;
-  data.load_end    = 0;
+  data.load_offset.a = 0;
+  data.load_start = 0;
+  data.load_end = 0;
 
   /* Parse the input arguments.  First is filename (required). */
   filename = scan_filename_with_cleanup (&args, NULL);
@@ -587,8 +598,8 @@ restore_command (char *args, int from_tty)
 	}
       /* Parse offset (optional). */
       if (args != NULL && *args != '\0')
-      data.load_offset = 
-	parse_and_eval_address (scan_expression_with_cleanup (&args, NULL));
+      data.load_offset = addr_to_offset (target_gdbarch,
+	parse_and_eval_address (scan_expression_with_cleanup (&args, NULL)));
       if (args != NULL && *args != '\0')
 	{
 	  /* Parse start address (optional). */
@@ -605,10 +616,10 @@ restore_command (char *args, int from_tty)
     }
 
   if (info_verbose)
-    printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
-		     filename, (unsigned long) data.load_offset, 
-		     (unsigned long) data.load_start, 
-		     (unsigned long) data.load_end);
+    printf_filtered ("Restore file %s offset %s start %s end %s\n",
+		     filename, paddress (target_gdbarch, data.load_offset.a),
+		     paddress (target_gdbarch, data.load_start),
+		     paddress (target_gdbarch, data.load_end));
 
   if (binary_flag)
     {
--- a/gdb/coff-pe-read.c
+++ b/gdb/coff-pe-read.c
@@ -36,7 +36,8 @@
 
 struct read_pe_section_data
 {
-  CORE_ADDR vma_offset;		/* Offset to loaded address of section. */
+  struct gdbarch *gdbarch;	/* gdbarch of this objfile.  */
+  addr_offset_t vma_offset;	/* Offset to loaded address of section. */
   unsigned long rva_start;	/* Start offset within the pe. */
   unsigned long rva_end;	/* End offset within the pe. */
   enum minimal_symbol_type ms_type;	/* Type to assign symbols in section. */
@@ -89,8 +90,10 @@ get_section_vmas (bfd *abfd, asection *sectp, void *context)
       /* Data within the section start at rva_start in the pe and at
          bfd_get_section_vma() within memory. Store the offset. */
 
-      sections[sectix].vma_offset
-	= bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
+      sections[sectix].vma_offset = addr_sub_to_offset (sections->gdbarch,
+						    bfd_get_section_vma (abfd,
+									 sectp),
+						    sections[sectix].rva_start);
     }
 }
 \f
@@ -104,7 +107,8 @@ add_pe_exported_sym (char *sym_name,
 {
   /* Add the stored offset to get the loaded address of the symbol. */
 
-  CORE_ADDR vma = func_rva + section_data->vma_offset;
+  CORE_ADDR vma = addr_add_offset (section_data->gdbarch, func_rva,
+				   section_data->vma_offset);
 
   char *qualified_name = 0;
   int dll_name_len = strlen (dll_name);
@@ -184,6 +188,7 @@ pe_as32 (void *ptr)
 void
 read_pe_exported_syms (struct objfile *objfile)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *dll = objfile->obfd;
   unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
   unsigned long export_rva, export_size, nsections, secptr, expptr;
@@ -198,9 +203,9 @@ read_pe_exported_syms (struct objfile *objfile)
      Initialization with start_rva > end_rva guarantees that
      unused sections won't be matched. */
   struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE]
-    = { {0, 1, 0, mst_text},
-  {0, 1, 0, mst_data},
-  {0, 1, 0, mst_bss}
+    = { {gdbarch, {0}, 1, 0, mst_text},
+  {gdbarch, {0}, 1, 0, mst_data},
+  {gdbarch, {0}, 1, 0, mst_bss}
   };
 
   struct cleanup *back_to = 0;
@@ -322,10 +327,10 @@ read_pe_exported_syms (struct objfile *objfile)
      assumes that *all* sections share the same relocation offset
      as the text section. */
   for (i = 0; i < PE_SECTION_TABLE_SIZE; i++)
-    {
-      section_data[i].vma_offset
-	+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-    }
+    section_data[i].vma_offset = addr_offset_add (gdbarch,
+						  section_data[i].vma_offset,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 
   /* Truncate name at first dot. Should maybe also convert to all
      lower case for convenience on Windows. */
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -779,7 +779,9 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 	{
 	  /* Record all functions -- external and static -- in minsyms. */
 	  int section = cs_to_section (cs, objfile);
-	  tmpaddr = cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	  tmpaddr = addr_add_offset (gdbarch, cs->c_value,
+				     ANOFFSET (objfile->section_offsets,
+					       SECT_OFF_TEXT (objfile)));
 	  record_minimal_symbol (cs, tmpaddr, mst_text, section, objfile);
 
 	  fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
@@ -844,8 +846,10 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 		     a file with debugging symbols
 		     followed by a later file with no symbols.  */
 		  if (in_source_file)
-		    complete_symtab (filestring,
-		    cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)),
+		    complete_symtab (filestring, addr_add_offset (gdbarch,
+								  cs->c_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile))),
 				     main_aux.x_scn.x_scnlen);
 		  in_source_file = 0;
 		}
@@ -915,7 +919,9 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
  		    || cs->c_sclass == C_THUMBEXTFUNC
  		    || cs->c_sclass == C_THUMBEXT
  		    || (pe_file && (cs->c_sclass == C_STAT)))
-		  tmpaddr += ANOFFSET (objfile->section_offsets, sec);
+		  tmpaddr = addr_add_offset (gdbarch, tmpaddr,
+					     ANOFFSET (objfile->section_offsets,
+						       sec));
 
 		if (bfd_section->flags & SEC_CODE)
 		  {
@@ -1034,9 +1040,11 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 
 	      finish_block (new->name, &local_symbols, new->old_blocks,
 			    new->start_addr,
-			    fcn_cs_saved.c_value
-			    + fcn_aux_saved.x_sym.x_misc.x_fsize
-			    + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)),
+			    addr_add_offset (gdbarch,
+			                     (fcn_cs_saved.c_value
+					  + fcn_aux_saved.x_sym.x_misc.x_fsize),
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile))),
 			    objfile
 		);
 	      within_function = 0;
@@ -1046,8 +1054,9 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 	case C_BLOCK:
 	  if (strcmp (cs->c_name, ".bb") == 0)
 	    {
-	      tmpaddr = cs->c_value;
-	      tmpaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	      tmpaddr = addr_add_offset (gdbarch, cs->c_value,
+					 ANOFFSET (objfile->section_offsets,
+						   SECT_OFF_TEXT (objfile)));
 	      push_context (++depth, tmpaddr);
 	    }
 	  else if (strcmp (cs->c_name, ".eb") == 0)
@@ -1070,8 +1079,9 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 		}
 	      if (local_symbols && context_stack_depth > 0)
 		{
-		  tmpaddr =
-		    cs->c_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		  tmpaddr = addr_add_offset (gdbarch, cs->c_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		  /* Make a block for the local symbols within.  */
 		  finish_block (0, &local_symbols, new->old_blocks,
 				new->start_addr, tmpaddr, objfile);
@@ -1387,8 +1397,11 @@ enter_linenos (long file_offset, int first_line,
 	 we exit. */
       if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line)
 	{
-	  CORE_ADDR addr = lptr.l_addr.l_paddr;
-	  addr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	  CORE_ADDR addr;
+
+	  addr = addr_add_offset (gdbarch, lptr.l_addr.l_paddr,
+	                          ANOFFSET (objfile->section_offsets,
+				            SECT_OFF_TEXT (objfile)));
 	  record_line (current_subfile, first_line + L_LNNO32 (&lptr),
 		       gdbarch_addr_bits_remove (gdbarch, addr));
 	}
@@ -1496,6 +1509,7 @@ process_coff_symbol (struct coff_symbol *cs,
 		     union internal_auxent *aux,
 		     struct objfile *objfile)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct symbol *sym
   = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
 				     sizeof (struct symbol));
@@ -1514,7 +1528,10 @@ process_coff_symbol (struct coff_symbol *cs,
 
   if (ISFCN (cs->c_type))
     {
-      SYMBOL_VALUE (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+      SYMBOL_VALUE (sym) = addr_add_offset (gdbarch,
+					    SYMBOL_VALUE (sym),
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
       SYMBOL_TYPE (sym) =
 	lookup_function_type (decode_function_type (cs, cs->c_type, aux, objfile));
 
@@ -1543,8 +1560,10 @@ process_coff_symbol (struct coff_symbol *cs,
 	case C_THUMBEXTFUNC:
 	case C_EXT:
 	  SYMBOL_CLASS (sym) = LOC_STATIC;
-	  SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
-	  SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	  SYMBOL_VALUE_ADDRESS (sym) = addr_add_offset (gdbarch,
+							(CORE_ADDR) cs->c_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 	  add_symbol_to_list (sym, &global_symbols);
 	  break;
 
@@ -1552,8 +1571,10 @@ process_coff_symbol (struct coff_symbol *cs,
 	case C_THUMBSTATFUNC:
 	case C_STAT:
 	  SYMBOL_CLASS (sym) = LOC_STATIC;
-	  SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
-	  SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	  SYMBOL_VALUE_ADDRESS (sym) = addr_add_offset (gdbarch,
+							(CORE_ADDR) cs->c_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 	  if (within_function)
 	    {
 	      /* Static symbol of local scope */
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -980,6 +980,7 @@ set_namestring (struct objfile *objfile, const struct internal_nlist *nlist)
 static void
 read_dbx_dynamic_symtab (struct objfile *objfile)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = objfile->obfd;
   struct cleanup *back_to;
   int counter;
@@ -1036,20 +1037,23 @@ read_dbx_dynamic_symtab (struct objfile *objfile)
 
 	  if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
 	    {
-	      sym_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_TEXT (objfile));
+	      sym_value = addr_add_offset (gdbarch, sym_value,
+					   ANOFFSET (objfile->section_offsets,
+						     SECT_OFF_TEXT (objfile)));
 	      type = N_TEXT;
 	    }
 	  else if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
 	    {
-	      sym_value	+= ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_DATA (objfile));
+	      sym_value	= addr_add_offset (gdbarch, sym_value,
+					   ANOFFSET (objfile->section_offsets,
+						     SECT_OFF_DATA (objfile)));
 	      type = N_DATA;
 	    }
 	  else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
 	    {
-	      sym_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_BSS (objfile));
+	      sym_value = addr_add_offset (gdbarch, sym_value,
+					   ANOFFSET (objfile->section_offsets,
+						     SECT_OFF_BSS (objfile)));
 	      type = N_BSS;
 	    }
 	  else
@@ -1089,9 +1093,9 @@ read_dbx_dynamic_symtab (struct objfile *objfile)
        counter++, relptr++)
     {
       arelent *rel = *relptr;
-      CORE_ADDR address =
-      rel->address + ANOFFSET (objfile->section_offsets,
-			       SECT_OFF_DATA (objfile));
+      CORE_ADDR address = addr_add_offset (gdbarch, rel->address,
+                                           ANOFFSET (objfile->section_offsets,
+					             SECT_OFF_DATA (objfile)));
 
       switch (bfd_get_arch (abfd))
 	{
@@ -1238,928 +1242,943 @@ read_dbx_symtab (struct objfile *objfile)
 
   last_source_file = NULL;
 
-  lowest_text_address = (CORE_ADDR) -1;
-
-  symfile_bfd = objfile->obfd;	/* For next_text_symbol */
-  abfd = objfile->obfd;
-  symbuf_end = symbuf_idx = 0;
-  next_symbol_text_func = dbx_next_symbol_text;
-  textlow_not_set = 1;
-  has_line_numbers = 0;
-
-  /* FIXME: jimb/2003-09-12: We don't apply the right section's offset
-     to global and static variables.  The stab for a global or static
-     variable doesn't give us any indication of which section it's in,
-     so we can't tell immediately which offset in
-     objfile->section_offsets we should apply to the variable's
-     address.
-
-     We could certainly find out which section contains the variable
-     by looking up the variable's unrelocated address with
-     find_pc_section, but that would be expensive; this is the
-     function that constructs the partial symbol tables by examining
-     every symbol in the entire executable, and it's
-     performance-critical.  So that expense would not be welcome.  I'm
-     not sure what to do about this at the moment.
-
-     What we have done for years is to simply assume that the .data
-     section's offset is appropriate for all global and static
-     variables.  Recently, this was expanded to fall back to the .bss
-     section's offset if there is no .data section, and then to the
-     .rodata section's offset.  */
-  data_sect_index = objfile->sect_index_data;
-  if (data_sect_index == -1)
-    data_sect_index = SECT_OFF_BSS (objfile);
-  if (data_sect_index == -1)
-    data_sect_index = SECT_OFF_RODATA (objfile);
-
-  /* If data_sect_index is still -1, that's okay.  It's perfectly fine
-     for the file to have no .data, no .bss, and no .text at all, if
-     it also has no global or static variables.  If it does, we will
-     get an internal error from an ANOFFSET macro below when we try to
-     use data_sect_index.  */
-
-  for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
-    {
-      /* Get the symbol for this run and pull out some info */
-      QUIT;			/* allow this to be interruptable */
-      if (symbuf_idx == symbuf_end)
-	fill_symbuf (abfd);
-      bufp = &symbuf[symbuf_idx++];
+lowest_text_address = addr_minus_one (gdbarch);
+
+symfile_bfd = objfile->obfd;	/* For next_text_symbol */
+abfd = objfile->obfd;
+symbuf_end = symbuf_idx = 0;
+next_symbol_text_func = dbx_next_symbol_text;
+textlow_not_set = 1;
+has_line_numbers = 0;
+
+/* FIXME: jimb/2003-09-12: We don't apply the right section's offset
+   to global and static variables.  The stab for a global or static
+   variable doesn't give us any indication of which section it's in,
+   so we can't tell immediately which offset in
+   objfile->section_offsets we should apply to the variable's
+   address.
+
+   We could certainly find out which section contains the variable
+   by looking up the variable's unrelocated address with
+   find_pc_section, but that would be expensive; this is the
+   function that constructs the partial symbol tables by examining
+   every symbol in the entire executable, and it's
+   performance-critical.  So that expense would not be welcome.  I'm
+   not sure what to do about this at the moment.
+
+   What we have done for years is to simply assume that the .data
+   section's offset is appropriate for all global and static
+   variables.  Recently, this was expanded to fall back to the .bss
+   section's offset if there is no .data section, and then to the
+   .rodata section's offset.  */
+data_sect_index = objfile->sect_index_data;
+if (data_sect_index == -1)
+  data_sect_index = SECT_OFF_BSS (objfile);
+if (data_sect_index == -1)
+  data_sect_index = SECT_OFF_RODATA (objfile);
+
+/* If data_sect_index is still -1, that's okay.  It's perfectly fine
+   for the file to have no .data, no .bss, and no .text at all, if
+   it also has no global or static variables.  If it does, we will
+   get an internal error from an ANOFFSET macro below when we try to
+   use data_sect_index.  */
+
+for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
+  {
+    /* Get the symbol for this run and pull out some info */
+    QUIT;			/* allow this to be interruptable */
+    if (symbuf_idx == symbuf_end)
+      fill_symbuf (abfd);
+    bufp = &symbuf[symbuf_idx++];
 
-      /*
-       * Special case to speed up readin.
-       */
-      if (bfd_h_get_8 (abfd, bufp->e_type) == N_SLINE)
-	{
-	  has_line_numbers = 1;
-	  continue;
-	}
+    /*
+     * Special case to speed up readin.
+     */
+    if (bfd_h_get_8 (abfd, bufp->e_type) == N_SLINE)
+      {
+	has_line_numbers = 1;
+	continue;
+      }
 
-      INTERNALIZE_SYMBOL (nlist, bufp, abfd);
-      OBJSTAT (objfile, n_stabs++);
+    INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+    OBJSTAT (objfile, n_stabs++);
 
-      /* Ok.  There is a lot of code duplicated in the rest of this
-         switch statement (for efficiency reasons).  Since I don't
-         like duplicating code, I will do my penance here, and
-         describe the code which is duplicated:
+    /* Ok.  There is a lot of code duplicated in the rest of this
+       switch statement (for efficiency reasons).  Since I don't
+       like duplicating code, I will do my penance here, and
+       describe the code which is duplicated:
 
-         *) The assignment to namestring.
-         *) The call to strchr.
-         *) The addition of a partial symbol the the two partial
-         symbol lists.  This last is a large section of code, so
-         I've imbedded it in the following macro.
-      */
+       *) The assignment to namestring.
+       *) The call to strchr.
+       *) The addition of a partial symbol the the two partial
+       symbol lists.  This last is a large section of code, so
+       I've imbedded it in the following macro.
+    */
 
-      switch (nlist.n_type)
-	{
-	  /*
-	   * Standard, external, non-debugger, symbols
-	   */
-
-	case N_TEXT | N_EXT:
-	case N_NBTEXT | N_EXT:
-	  nlist.n_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_TEXT (objfile));
+    switch (nlist.n_type)
+      {
+	/*
+	 * Standard, external, non-debugger, symbols
+	 */
+
+      case N_TEXT | N_EXT:
+      case N_NBTEXT | N_EXT:
+	nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					 ANOFFSET (objfile->section_offsets,
+						   SECT_OFF_TEXT (objfile)));
+	goto record_it;
+
+      case N_DATA | N_EXT:
+      case N_NBDATA | N_EXT:
+	nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					 ANOFFSET (objfile->section_offsets,
+						   SECT_OFF_DATA (objfile)));
+	goto record_it;
+
+      case N_BSS:
+      case N_BSS | N_EXT:
+      case N_NBBSS | N_EXT:
+      case N_SETV | N_EXT:		/* FIXME, is this in BSS? */
+	nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					 ANOFFSET (objfile->section_offsets,
+						   SECT_OFF_BSS (objfile)));
+	goto record_it;
+
+      case N_ABS | N_EXT:
+	record_it:
+	namestring = set_namestring (objfile, &nlist);
+
+      bss_ext_symbol:
+	record_minimal_symbol (namestring, nlist.n_value,
+			       nlist.n_type, objfile);	/* Always */
+	continue;
+
+	/* Standard, local, non-debugger, symbols */
+
+      case N_NBTEXT:
+
+	/* We need to be able to deal with both N_FN or N_TEXT,
+	   because we have no way of knowing whether the sys-supplied ld
+	   or GNU ld was used to make the executable.  Sequents throw
+	   in another wrinkle -- they renumbered N_FN.  */
+
+      case N_FN:
+      case N_FN_SEQ:
+      case N_TEXT:
+	nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					 ANOFFSET (objfile->section_offsets,
+						   SECT_OFF_TEXT (objfile)));
+	namestring = set_namestring (objfile, &nlist);
+
+	if ((namestring[0] == '-' && namestring[1] == 'l')
+	    || (namestring[(nsl = strlen (namestring)) - 1] == 'o'
+		&& namestring[nsl - 2] == '.'))
+	  {
+	    if (past_first_source_file && pst
+		/* The gould NP1 uses low values for .o and -l symbols
+		   which are not the address.  */
+		&& nlist.n_value >= pst->textlow)
+	      {
+		end_psymtab (pst, psymtab_include_list, includes_used,
+			     symnum * symbol_size,
+			     nlist.n_value > pst->texthigh
+			     ? nlist.n_value : pst->texthigh,
+			     dependency_list, dependencies_used,
+			     textlow_not_set);
+		pst = (struct partial_symtab *) 0;
+		includes_used = 0;
+		dependencies_used = 0;
+		has_line_numbers = 0;
+	      }
+	    else
+	      past_first_source_file = 1;
+	    last_o_file_start = nlist.n_value;
+	  }
+	else
 	  goto record_it;
+	continue;
 
-	case N_DATA | N_EXT:
-	case N_NBDATA | N_EXT:
-	  nlist.n_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_DATA (objfile));
-	  goto record_it;
+      case N_DATA:
+	nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					 ANOFFSET (objfile->section_offsets,
+						   SECT_OFF_DATA (objfile)));
+	goto record_it;
 
-	case N_BSS:
-	case N_BSS | N_EXT:
-	case N_NBBSS | N_EXT:
-	case N_SETV | N_EXT:		/* FIXME, is this in BSS? */
-	  nlist.n_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_BSS (objfile));
-	  goto record_it;
+      case N_UNDF | N_EXT:
+	if (nlist.n_value != 0)
+	  {
+	    /* This is a "Fortran COMMON" symbol.  See if the target
+	       environment knows where it has been relocated to.  */
 
-	case N_ABS | N_EXT:
-	  record_it:
-	  namestring = set_namestring (objfile, &nlist);
+	    CORE_ADDR reladdr;
 
-	bss_ext_symbol:
-	  record_minimal_symbol (namestring, nlist.n_value,
-				 nlist.n_type, objfile);	/* Always */
-	  continue;
+	    namestring = set_namestring (objfile, &nlist);
+	    if (target_lookup_symbol (namestring, &reladdr))
+	      {
+		continue;	/* Error in lookup; ignore symbol for now.  */
+	      }
+	    nlist.n_type ^= (N_BSS ^ N_UNDF);	/* Define it as a bss-symbol */
+	    nlist.n_value = reladdr;
+	    goto bss_ext_symbol;
+	  }
+	continue;			/* Just undefined, not COMMON */
 
-	  /* Standard, local, non-debugger, symbols */
+      case N_UNDF:
+	if (processing_acc_compilation && nlist.n_strx == 1)
+	  {
+	    /* Deal with relative offsets in the string table
+	       used in ELF+STAB under Solaris.  If we want to use the
+	       n_strx field, which contains the name of the file,
+	       we must adjust file_string_table_offset *before* calling
+	       set_namestring().  */
+	    past_first_source_file = 1;
+	    file_string_table_offset = next_file_string_table_offset;
+	    next_file_string_table_offset =
+	      file_string_table_offset + nlist.n_value;
+	    if (next_file_string_table_offset < file_string_table_offset)
+	      error (_("string table offset backs up at %d"), symnum);
+	    /* FIXME -- replace error() with complaint.  */
+	    continue;
+	  }
+	continue;
+
+	/* Lots of symbol types we can just ignore.  */
+
+      case N_ABS:
+      case N_NBDATA:
+      case N_NBBSS:
+	continue;
+
+	/* Keep going . . . */
+
+	/*
+	 * Special symbol types for GNU
+	 */
+      case N_INDR:
+      case N_INDR | N_EXT:
+      case N_SETA:
+      case N_SETA | N_EXT:
+      case N_SETT:
+      case N_SETT | N_EXT:
+      case N_SETD:
+      case N_SETD | N_EXT:
+      case N_SETB:
+      case N_SETB | N_EXT:
+      case N_SETV:
+	continue;
+
+	/*
+	 * Debugger symbols
+	 */
+
+      case N_SO:
+	{
+	  CORE_ADDR valu;
+	  static int prev_so_symnum = -10;
+	  static int first_so_symnum;
+	  char *p;
+	  static char *dirname_nso;
+	  int prev_textlow_not_set;
 
-	case N_NBTEXT:
+	  nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					  ANOFFSET (objfile->section_offsets,
+						    SECT_OFF_TEXT (objfile)));
+	  valu = nlist.n_value;
 
-	  /* We need to be able to deal with both N_FN or N_TEXT,
-	     because we have no way of knowing whether the sys-supplied ld
-	     or GNU ld was used to make the executable.  Sequents throw
-	     in another wrinkle -- they renumbered N_FN.  */
+	  prev_textlow_not_set = textlow_not_set;
 
-	case N_FN:
-	case N_FN_SEQ:
-	case N_TEXT:
-	  nlist.n_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_TEXT (objfile));
-	  namestring = set_namestring (objfile, &nlist);
+	  /* A zero value is probably an indication for the SunPRO 3.0
+	     compiler. end_psymtab explicitly tests for zero, so
+	     don't relocate it.  */
 
-	  if ((namestring[0] == '-' && namestring[1] == 'l')
-	      || (namestring[(nsl = strlen (namestring)) - 1] == 'o'
-		  && namestring[nsl - 2] == '.'))
+	  if (nlist.n_value == 0
+	      && gdbarch_sofun_address_maybe_missing (gdbarch))
 	    {
-	      if (past_first_source_file && pst
-		  /* The gould NP1 uses low values for .o and -l symbols
-		     which are not the address.  */
-		  && nlist.n_value >= pst->textlow)
+	      textlow_not_set = 1;
+	      valu = 0;
+	    }
+	  else
+	    textlow_not_set = 0;
+
+	  past_first_source_file = 1;
+
+	  if (prev_so_symnum != symnum - 1)
+	    {			/* Here if prev stab wasn't N_SO */
+	      first_so_symnum = symnum;
+
+	      if (pst)
 		{
 		  end_psymtab (pst, psymtab_include_list, includes_used,
 			       symnum * symbol_size,
-			       nlist.n_value > pst->texthigh
-			       ? nlist.n_value : pst->texthigh,
+			       valu > pst->texthigh ? valu : pst->texthigh,
 			       dependency_list, dependencies_used,
-			       textlow_not_set);
+			       prev_textlow_not_set);
 		  pst = (struct partial_symtab *) 0;
 		  includes_used = 0;
 		  dependencies_used = 0;
 		  has_line_numbers = 0;
 		}
-	      else
-		past_first_source_file = 1;
-	      last_o_file_start = nlist.n_value;
 	    }
-	  else
-	    goto record_it;
-	  continue;
 
-	case N_DATA:
-	  nlist.n_value += ANOFFSET (objfile->section_offsets,
-				     SECT_OFF_DATA (objfile));
-	  goto record_it;
+	  prev_so_symnum = symnum;
+
+	  /* End the current partial symtab and start a new one */
 
-	case N_UNDF | N_EXT:
-	  if (nlist.n_value != 0)
+	  namestring = set_namestring (objfile, &nlist);
+
+	  /* Null name means end of .o file.  Don't start a new one. */
+	  if (*namestring == '\000')
+	    continue;
+
+	  /* Some compilers (including gcc) emit a pair of initial N_SOs.
+	     The first one is a directory name; the second the file name.
+	     If pst exists, is empty, and has a filename ending in '/',
+	     we assume the previous N_SO was a directory name. */
+
+	  p = strrchr (namestring, '/');
+	  if (p && *(p + 1) == '\000')
 	    {
-	      /* This is a "Fortran COMMON" symbol.  See if the target
-		 environment knows where it has been relocated to.  */
+	      /* Save the directory name SOs locally, then save it into
+		 the psymtab when it's created below. */
+	      dirname_nso = namestring;
+	      continue;		
+	    }
 
-	      CORE_ADDR reladdr;
+	  /* Some other compilers (C++ ones in particular) emit useless
+	     SOs for non-existant .c files.  We ignore all subsequent SOs
+	     that immediately follow the first.  */
 
-	      namestring = set_namestring (objfile, &nlist);
-	      if (target_lookup_symbol (namestring, &reladdr))
-		{
-		  continue;	/* Error in lookup; ignore symbol for now.  */
-		}
-	      nlist.n_type ^= (N_BSS ^ N_UNDF);	/* Define it as a bss-symbol */
-	      nlist.n_value = reladdr;
-	      goto bss_ext_symbol;
+	  if (!pst)
+	    {
+	      pst = start_psymtab (objfile,
+				   namestring, valu,
+				   first_so_symnum * symbol_size,
+				   objfile->global_psymbols.next,
+				   objfile->static_psymbols.next);
+	      pst->dirname = dirname_nso;
+	      dirname_nso = NULL;
 	    }
-	  continue;			/* Just undefined, not COMMON */
+	  continue;
+	}
+
+      case N_BINCL:
+	{
+	  enum language tmp_language;
+	  /* Add this bincl to the bincl_list for future EXCLs.  No
+	     need to save the string; it'll be around until
+	     read_dbx_symtab function returns */
 
-	case N_UNDF:
-	  if (processing_acc_compilation && nlist.n_strx == 1)
+	  namestring = set_namestring (objfile, &nlist);
+	  tmp_language = deduce_language_from_filename (namestring);
+
+	  /* Only change the psymtab's language if we've learned
+	     something useful (eg. tmp_language is not language_unknown).
+	     In addition, to match what start_subfile does, never change
+	     from C++ to C.  */
+	  if (tmp_language != language_unknown
+	      && (tmp_language != language_c
+		  || psymtab_language != language_cplus))
+	    psymtab_language = tmp_language;
+
+	  if (pst == NULL)
 	    {
-	      /* Deal with relative offsets in the string table
-		 used in ELF+STAB under Solaris.  If we want to use the
-		 n_strx field, which contains the name of the file,
-		 we must adjust file_string_table_offset *before* calling
-		 set_namestring().  */
-	      past_first_source_file = 1;
-	      file_string_table_offset = next_file_string_table_offset;
-	      next_file_string_table_offset =
-		file_string_table_offset + nlist.n_value;
-	      if (next_file_string_table_offset < file_string_table_offset)
-		error (_("string table offset backs up at %d"), symnum);
-	      /* FIXME -- replace error() with complaint.  */
+	      /* FIXME: we should not get here without a PST to work on.
+		 Attempt to recover.  */
+	      complaint (&symfile_complaints,
+			 _("N_BINCL %s not in entries for any file, at symtab \
+pos %d"),
+			 namestring, symnum);
 	      continue;
 	    }
-	  continue;
+	  add_bincl_to_list (pst, namestring, nlist.n_value);
 
-	  /* Lots of symbol types we can just ignore.  */
+	  /* Mark down an include file in the current psymtab */
 
-	case N_ABS:
-	case N_NBDATA:
-	case N_NBBSS:
-	  continue;
+	  goto record_include_file;
+	}
+
+      case N_SOL:
+	{
+	  enum language tmp_language;
+	  /* Mark down an include file in the current psymtab */
+
+	  namestring = set_namestring (objfile, &nlist);
+	  tmp_language = deduce_language_from_filename (namestring);
+
+	  /* Only change the psymtab's language if we've learned
+	     something useful (eg. tmp_language is not language_unknown).
+	     In addition, to match what start_subfile does, never change
+	     from C++ to C.  */
+	  if (tmp_language != language_unknown
+	      && (tmp_language != language_c
+		  || psymtab_language != language_cplus))
+	    psymtab_language = tmp_language;
+
+	  /* In C++, one may expect the same filename to come round many
+	     times, when code is coming alternately from the main file
+	     and from inline functions in other files. So I check to see
+	     if this is a file we've seen before -- either the main
+	     source file, or a previously included file.
+
+	     This seems to be a lot of time to be spending on N_SOL, but
+	     things like "break c-exp.y:435" need to work (I
+	     suppose the psymtab_include_list could be hashed or put
+	     in a binary tree, if profiling shows this is a major hog).  */
+	  if (pst && strcmp (namestring, pst->filename) == 0)
+	    continue;
+	  {
+	    int i;
+	    for (i = 0; i < includes_used; i++)
+	      if (strcmp (namestring, psymtab_include_list[i]) == 0)
+		{
+		  i = -1;
+		  break;
+		}
+	    if (i == -1)
+	      continue;
+	  }
+
+	record_include_file:
+
+	  psymtab_include_list[includes_used++] = namestring;
+	  if (includes_used >= includes_allocated)
+	    {
+	      char **orig = psymtab_include_list;
 
-	  /* Keep going . . . */
-
-	  /*
-	   * Special symbol types for GNU
-	   */
-	case N_INDR:
-	case N_INDR | N_EXT:
-	case N_SETA:
-	case N_SETA | N_EXT:
-	case N_SETT:
-	case N_SETT | N_EXT:
-	case N_SETD:
-	case N_SETD | N_EXT:
-	case N_SETB:
-	case N_SETB | N_EXT:
-	case N_SETV:
+	      psymtab_include_list = (char **)
+		alloca ((includes_allocated *= 2) * sizeof (char *));
+	      memcpy (psymtab_include_list, orig,
+		      includes_used * sizeof (char *));
+	    }
 	  continue;
+	}
+      case N_LSYM:		/* Typedef or automatic variable. */
+      case N_STSYM:		/* Data seg var -- static  */
+      case N_LCSYM:		/* BSS      "  */
+      case N_ROSYM:		/* Read-only data seg var -- static.  */
+      case N_NBSTS:		/* Gould nobase.  */
+      case N_NBLCS:		/* symbols.  */
+      case N_FUN:
+      case N_GSYM:		/* Global (extern) variable; can be
+				 data or bss (sigh FIXME).  */
+
+	/* Following may probably be ignored; I'll leave them here
+	   for now (until I do Pascal and Modula 2 extensions).  */
+
+      case N_PC:		/* I may or may not need this; I
+				 suspect not.  */
+      case N_M2C:		/* I suspect that I can ignore this here. */
+      case N_SCOPE:		/* Same.   */
+      {
+	char *p;
 
-	  /*
-	   * Debugger symbols
-	   */
+	namestring = set_namestring (objfile, &nlist);
 
-	case N_SO:
+	/* See if this is an end of function stab.  */
+	if (pst && nlist.n_type == N_FUN && *namestring == '\000')
 	  {
 	    CORE_ADDR valu;
-	    static int prev_so_symnum = -10;
-	    static int first_so_symnum;
-	    char *p;
-	    static char *dirname_nso;
-	    int prev_textlow_not_set;
 
-	    valu = nlist.n_value + ANOFFSET (objfile->section_offsets,
-					     SECT_OFF_TEXT (objfile));
-
-	    prev_textlow_not_set = textlow_not_set;
+	    /* It's value is the size (in bytes) of the function for
+	       function relative stabs, or the address of the function's
+	       end for old style stabs.  */
+	    valu = nlist.n_value + last_function_start;
+	    if (pst->texthigh == 0 || valu > pst->texthigh)
+	      pst->texthigh = valu;
+	    break;
+	  }
 
-	    /* A zero value is probably an indication for the SunPRO 3.0
-	       compiler. end_psymtab explicitly tests for zero, so
-	       don't relocate it.  */
+	p = (char *) strchr (namestring, ':');
+	if (!p)
+	  continue;			/* Not a debugging symbol.   */
 
-	    if (nlist.n_value == 0
-		&& gdbarch_sofun_address_maybe_missing (gdbarch))
+	sym_len = 0;
+	sym_name = NULL;	/* pacify "gcc -Werror" */
+	if (psymtab_language == language_cplus)
+	  {
+	    char *new_name, *name = xmalloc (p - namestring + 1);
+	    memcpy (name, namestring, p - namestring);
+	    name[p - namestring] = '\0';
+	    new_name = cp_canonicalize_string (name);
+	    if (new_name != NULL)
 	      {
-		textlow_not_set = 1;
-		valu = 0;
+		sym_len = strlen (new_name);
+		sym_name = obsavestring (new_name, sym_len,
+					 &objfile->objfile_obstack);
+		xfree (new_name);
 	      }
-	    else
-	      textlow_not_set = 0;
+	    xfree (name);
+	  }
 
-	    past_first_source_file = 1;
+	if (sym_len == 0)
+	  {
+	    sym_name = namestring;
+	    sym_len = p - namestring;
+	  }
+
+	/* Main processing section for debugging symbols which
+	   the initial read through the symbol tables needs to worry
+	   about.  If we reach this point, the symbol which we are
+	   considering is definitely one we are interested in.
+	   p must also contain the (valid) index into the namestring
+	   which indicates the debugging type symbol.  */
+
+	switch (p[1])
+	  {
+	  case 'S':
+	    nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					   ANOFFSET (objfile->section_offsets,
+						     data_sect_index));
+
+	    if (gdbarch_static_transform_name_p (gdbarch))
+	      namestring = gdbarch_static_transform_name (gdbarch,
+							  namestring);
+
+	    add_psymbol_to_list (sym_name, sym_len, 1,
+				 VAR_DOMAIN, LOC_STATIC,
+				 &objfile->static_psymbols,
+				 0, nlist.n_value,
+				 psymtab_language, objfile);
+	    continue;
 
-	    if (prev_so_symnum != symnum - 1)
-	      {			/* Here if prev stab wasn't N_SO */
-		first_so_symnum = symnum;
+	  case 'G':
+	    nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					   ANOFFSET (objfile->section_offsets,
+						     data_sect_index));
+
+	    /* The addresses in these entries are reported to be
+	       wrong.  See the code that reads 'G's for symtabs. */
+	    add_psymbol_to_list (sym_name, sym_len, 1,
+				 VAR_DOMAIN, LOC_STATIC,
+				 &objfile->global_psymbols,
+				 0, nlist.n_value,
+				 psymtab_language, objfile);
+	    continue;
 
-		if (pst)
+	  case 'T':
+	    /* When a 'T' entry is defining an anonymous enum, it
+	       may have a name which is the empty string, or a
+	       single space.  Since they're not really defining a
+	       symbol, those shouldn't go in the partial symbol
+	       table.  We do pick up the elements of such enums at
+	       'check_enum:', below.  */
+	    if (p >= namestring + 2
+		|| (p == namestring + 1
+		    && namestring[0] != ' '))
+	      {
+		add_psymbol_to_list (sym_name, sym_len, 1,
+				     STRUCT_DOMAIN, LOC_TYPEDEF,
+				     &objfile->static_psymbols,
+				     nlist.n_value, 0,
+				     psymtab_language, objfile);
+		if (p[2] == 't')
 		  {
-		    end_psymtab (pst, psymtab_include_list, includes_used,
-				 symnum * symbol_size,
-				 valu > pst->texthigh ? valu : pst->texthigh,
-				 dependency_list, dependencies_used,
-				 prev_textlow_not_set);
-		    pst = (struct partial_symtab *) 0;
-		    includes_used = 0;
-		    dependencies_used = 0;
-		    has_line_numbers = 0;
+		    /* Also a typedef with the same name.  */
+		    add_psymbol_to_list (sym_name, sym_len, 1,
+					 VAR_DOMAIN, LOC_TYPEDEF,
+					 &objfile->static_psymbols,
+					 nlist.n_value, 0,
+					 psymtab_language, objfile);
+		    p += 1;
 		  }
 	      }
+	    goto check_enum;
 
-	    prev_so_symnum = symnum;
-
-	    /* End the current partial symtab and start a new one */
+	  case 't':
+	    if (p != namestring)	/* a name is there, not just :T... */
+	      {
+		add_psymbol_to_list (sym_name, sym_len, 1,
+				     VAR_DOMAIN, LOC_TYPEDEF,
+				     &objfile->static_psymbols,
+				     nlist.n_value, 0,
+				     psymtab_language, objfile);
+	      }
+	  check_enum:
+	    /* If this is an enumerated type, we need to
+	       add all the enum constants to the partial symbol
+	       table.  This does not cover enums without names, e.g.
+	       "enum {a, b} c;" in C, but fortunately those are
+	       rare.  There is no way for GDB to find those from the
+	       enum type without spending too much time on it.  Thus
+	       to solve this problem, the compiler needs to put out the
+	       enum in a nameless type.  GCC2 does this.  */
+
+	    /* We are looking for something of the form
+	       <name> ":" ("t" | "T") [<number> "="] "e"
+	       {<constant> ":" <value> ","} ";".  */
+
+	    /* Skip over the colon and the 't' or 'T'.  */
+	    p += 2;
+	    /* This type may be given a number.  Also, numbers can come
+	       in pairs like (0,26).  Skip over it.  */
+	    while ((*p >= '0' && *p <= '9')
+		   || *p == '(' || *p == ',' || *p == ')'
+		   || *p == '=')
+	      p++;
+
+	    if (*p++ == 'e')
+	      {
+		/* The aix4 compiler emits extra crud before the members.  */
+		if (*p == '-')
+		  {
+		    /* Skip over the type (?).  */
+		    while (*p != ':')
+		      p++;
 
-	    namestring = set_namestring (objfile, &nlist);
+		    /* Skip over the colon.  */
+		    p++;
+		  }
 
-	    /* Null name means end of .o file.  Don't start a new one. */
-	    if (*namestring == '\000')
-	      continue;
+		/* We have found an enumerated type.  */
+		/* According to comments in read_enum_type
+		   a comma could end it instead of a semicolon.
+		   I don't know where that happens.
+		   Accept either.  */
+		while (*p && *p != ';' && *p != ',')
+		  {
+		    char *q;
+
+		    /* Check for and handle cretinous dbx symbol name
+		       continuation!  */
+		    if (*p == '\\' || (*p == '?' && p[1] == '\0'))
+		      p = next_symbol_text (objfile);
+
+		    /* Point to the character after the name
+		       of the enum constant.  */
+		    for (q = p; *q && *q != ':'; q++)
+		      ;
+		    /* Note that the value doesn't matter for
+		       enum constants in psymtabs, just in symtabs.  */
+		    add_psymbol_to_list (p, q - p, 1,
+					 VAR_DOMAIN, LOC_CONST,
+					 &objfile->static_psymbols, 0,
+					 0, psymtab_language, objfile);
+		    /* Point past the name.  */
+		    p = q;
+		    /* Skip over the value.  */
+		    while (*p && *p != ',')
+		      p++;
+		    /* Advance past the comma.  */
+		    if (*p)
+		      p++;
+		  }
+	      }
+	    continue;
 
-	    /* Some compilers (including gcc) emit a pair of initial N_SOs.
-	       The first one is a directory name; the second the file name.
-	       If pst exists, is empty, and has a filename ending in '/',
-	       we assume the previous N_SO was a directory name. */
+	  case 'c':
+	    /* Constant, e.g. from "const" in Pascal.  */
+	    add_psymbol_to_list (sym_name, sym_len, 1,
+				 VAR_DOMAIN, LOC_CONST,
+				 &objfile->static_psymbols, nlist.n_value,
+				 0, psymtab_language, objfile);
+	    continue;
 
-	    p = strrchr (namestring, '/');
-	    if (p && *(p + 1) == '\000')
+	  case 'f':
+	    if (! pst)
 	      {
-		/* Save the directory name SOs locally, then save it into
-		   the psymtab when it's created below. */
-	        dirname_nso = namestring;
-	        continue;		
+		int name_len = p - namestring;
+		char *name = xmalloc (name_len + 1);
+		memcpy (name, namestring, name_len);
+		name[name_len] = '\0';
+		function_outside_compilation_unit_complaint (name);
+		xfree (name);
 	      }
-
-	    /* Some other compilers (C++ ones in particular) emit useless
-	       SOs for non-existant .c files.  We ignore all subsequent SOs
-	       that immediately follow the first.  */
-
-	    if (!pst)
+	    /* Kludges for ELF/STABS with Sun ACC */
+	    last_function_name = namestring;
+	    /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
+	       value for the bottom of the text seg in those cases. */
+	    if (nlist.n_value == 0
+		&& gdbarch_sofun_address_maybe_missing (gdbarch))
+	      {
+		CORE_ADDR minsym_valu = 
+		  find_stab_function_addr (namestring, 
+					   pst ? pst->filename : NULL, 
+					   objfile);
+		/* find_stab_function_addr will return 0 if the minimal
+		   symbol wasn't found.  (Unfortunately, this might also
+		   be a valid address.)  Anyway, if it *does* return 0,
+		   it is likely that the value was set correctly to begin
+		   with... */
+		if (minsym_valu != 0)
+		  nlist.n_value = minsym_valu;
+	      }
+	    else
+	      nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					  ANOFFSET (objfile->section_offsets,
+						    SECT_OFF_TEXT (objfile)));
+	    if (pst && textlow_not_set
+		&& gdbarch_sofun_address_maybe_missing (gdbarch))
+	      {
+		pst->textlow = nlist.n_value;
+		textlow_not_set = 0;
+	      }
+	    /* End kludge.  */
+
+	    /* Keep track of the start of the last function so we
+	       can handle end of function symbols.  */
+	    last_function_start = nlist.n_value;
+
+	    /* In reordered executables this function may lie outside
+	       the bounds created by N_SO symbols.  If that's the case
+	       use the address of this function as the low bound for
+	       the partial symbol table.  */
+	    if (pst
+		&& (textlow_not_set
+		    || (nlist.n_value < pst->textlow
+			&& (addr_sub_offset (gdbarch, nlist.n_value,
+					  ANOFFSET (objfile->section_offsets,
+						    SECT_OFF_TEXT (objfile)))
+			    != 0))))
 	      {
-		pst = start_psymtab (objfile,
-				     namestring, valu,
-				     first_so_symnum * symbol_size,
-				     objfile->global_psymbols.next,
-				     objfile->static_psymbols.next);
-		pst->dirname = dirname_nso;
-		dirname_nso = NULL;
+		pst->textlow = nlist.n_value;
+		textlow_not_set = 0;
 	      }
+	    add_psymbol_to_list (sym_name, sym_len, 1,
+				 VAR_DOMAIN, LOC_BLOCK,
+				 &objfile->static_psymbols,
+				 0, nlist.n_value,
+				 psymtab_language, objfile);
 	    continue;
-	  }
-
-	case N_BINCL:
-	  {
-	    enum language tmp_language;
-	    /* Add this bincl to the bincl_list for future EXCLs.  No
-	       need to save the string; it'll be around until
-	       read_dbx_symtab function returns */
 
-	    namestring = set_namestring (objfile, &nlist);
-	    tmp_language = deduce_language_from_filename (namestring);
-
-	    /* Only change the psymtab's language if we've learned
-	       something useful (eg. tmp_language is not language_unknown).
-	       In addition, to match what start_subfile does, never change
-	       from C++ to C.  */
-	    if (tmp_language != language_unknown
-		&& (tmp_language != language_c
-		    || psymtab_language != language_cplus))
-	      psymtab_language = tmp_language;
-
-	    if (pst == NULL)
+	    /* Global functions were ignored here, but now they
+	       are put into the global psymtab like one would expect.
+	       They're also in the minimal symbol table.  */
+	  case 'F':
+	    if (! pst)
 	      {
-		/* FIXME: we should not get here without a PST to work on.
-		   Attempt to recover.  */
-		complaint (&symfile_complaints,
-			   _("N_BINCL %s not in entries for any file, at symtab \
-pos %d"),
-			   namestring, symnum);
-		continue;
+		int name_len = p - namestring;
+		char *name = xmalloc (name_len + 1);
+		memcpy (name, namestring, name_len);
+		name[name_len] = '\0';
+		function_outside_compilation_unit_complaint (name);
+		xfree (name);
 	      }
-	    add_bincl_to_list (pst, namestring, nlist.n_value);
-
-	    /* Mark down an include file in the current psymtab */
-
-	    goto record_include_file;
-	  }
-
-	case N_SOL:
-	  {
-	    enum language tmp_language;
-	    /* Mark down an include file in the current psymtab */
-
-	    namestring = set_namestring (objfile, &nlist);
-	    tmp_language = deduce_language_from_filename (namestring);
-
-	    /* Only change the psymtab's language if we've learned
-	       something useful (eg. tmp_language is not language_unknown).
-	       In addition, to match what start_subfile does, never change
-	       from C++ to C.  */
-	    if (tmp_language != language_unknown
-		&& (tmp_language != language_c
-		    || psymtab_language != language_cplus))
-	      psymtab_language = tmp_language;
-
-	    /* In C++, one may expect the same filename to come round many
-	       times, when code is coming alternately from the main file
-	       and from inline functions in other files. So I check to see
-	       if this is a file we've seen before -- either the main
-	       source file, or a previously included file.
-
-	       This seems to be a lot of time to be spending on N_SOL, but
-	       things like "break c-exp.y:435" need to work (I
-	       suppose the psymtab_include_list could be hashed or put
-	       in a binary tree, if profiling shows this is a major hog).  */
-	    if (pst && strcmp (namestring, pst->filename) == 0)
-	      continue;
-	    {
-	      int i;
-	      for (i = 0; i < includes_used; i++)
-		if (strcmp (namestring, psymtab_include_list[i]) == 0)
-		  {
-		    i = -1;
-		    break;
-		  }
-	      if (i == -1)
-		continue;
-	    }
-
-	  record_include_file:
-
-	    psymtab_include_list[includes_used++] = namestring;
-	    if (includes_used >= includes_allocated)
+	    /* Kludges for ELF/STABS with Sun ACC */
+	    last_function_name = namestring;
+	    /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
+	       value for the bottom of the text seg in those cases. */
+	    if (nlist.n_value == 0
+		&& gdbarch_sofun_address_maybe_missing (gdbarch))
 	      {
-		char **orig = psymtab_include_list;
-
-		psymtab_include_list = (char **)
-		  alloca ((includes_allocated *= 2) * sizeof (char *));
-		memcpy (psymtab_include_list, orig,
-			includes_used * sizeof (char *));
+		CORE_ADDR minsym_valu = 
+		  find_stab_function_addr (namestring, 
+					   pst ? pst->filename : NULL, 
+					   objfile);
+		/* find_stab_function_addr will return 0 if the minimal
+		   symbol wasn't found.  (Unfortunately, this might also
+		   be a valid address.)  Anyway, if it *does* return 0,
+		   it is likely that the value was set correctly to begin
+		   with... */
+		if (minsym_valu != 0)
+		  nlist.n_value = minsym_valu;
 	      }
+	    else
+	      nlist.n_value = addr_add_offset (gdbarch, nlist.n_value,
+					  ANOFFSET (objfile->section_offsets,
+						    SECT_OFF_TEXT (objfile)));
+	    if (pst && textlow_not_set
+		&& gdbarch_sofun_address_maybe_missing (gdbarch))
+	      {
+		pst->textlow = nlist.n_value;
+		textlow_not_set = 0;
+	      }
+	    /* End kludge.  */
+
+	    /* Keep track of the start of the last function so we
+	       can handle end of function symbols.  */
+	    last_function_start = nlist.n_value;
+
+	    /* In reordered executables this function may lie outside
+	       the bounds created by N_SO symbols.  If that's the case
+	       use the address of this function as the low bound for
+	       the partial symbol table.  */
+	    if (pst
+		&& (textlow_not_set
+		    || (nlist.n_value < pst->textlow
+			&& (addr_sub_offset (gdbarch, nlist.n_value,
+					  ANOFFSET (objfile->section_offsets,
+						    SECT_OFF_TEXT (objfile)))
+			    != 0))))
+	      {
+		pst->textlow = nlist.n_value;
+		textlow_not_set = 0;
+	      }
+	    add_psymbol_to_list (sym_name, sym_len, 1,
+				 VAR_DOMAIN, LOC_BLOCK,
+				 &objfile->global_psymbols,
+				 0, nlist.n_value,
+				 psymtab_language, objfile);
 	    continue;
-	  }
-	case N_LSYM:		/* Typedef or automatic variable. */
-	case N_STSYM:		/* Data seg var -- static  */
-	case N_LCSYM:		/* BSS      "  */
-	case N_ROSYM:		/* Read-only data seg var -- static.  */
-	case N_NBSTS:		/* Gould nobase.  */
-	case N_NBLCS:		/* symbols.  */
-	case N_FUN:
-	case N_GSYM:		/* Global (extern) variable; can be
-				   data or bss (sigh FIXME).  */
-
-	  /* Following may probably be ignored; I'll leave them here
-	     for now (until I do Pascal and Modula 2 extensions).  */
-
-	case N_PC:		/* I may or may not need this; I
-				   suspect not.  */
-	case N_M2C:		/* I suspect that I can ignore this here. */
-	case N_SCOPE:		/* Same.   */
-	{
-	  char *p;
-
-	  namestring = set_namestring (objfile, &nlist);
 
-	  /* See if this is an end of function stab.  */
-	  if (pst && nlist.n_type == N_FUN && *namestring == '\000')
-	    {
-	      CORE_ADDR valu;
-
-	      /* It's value is the size (in bytes) of the function for
-		 function relative stabs, or the address of the function's
-		 end for old style stabs.  */
-	      valu = nlist.n_value + last_function_start;
-	      if (pst->texthigh == 0 || valu > pst->texthigh)
-		pst->texthigh = valu;
-	      break;
-	    }
-
-	  p = (char *) strchr (namestring, ':');
-	  if (!p)
-	    continue;			/* Not a debugging symbol.   */
+	    /* Two things show up here (hopefully); static symbols of
+	       local scope (static used inside braces) or extensions
+	       of structure symbols.  We can ignore both.  */
+	  case 'V':
+	  case '(':
+	  case '0':
+	  case '1':
+	  case '2':
+	  case '3':
+	  case '4':
+	  case '5':
+	  case '6':
+	  case '7':
+	  case '8':
+	  case '9':
+	  case '-':
+	  case '#':	/* for symbol identification (used in live ranges) */
+	    continue;
 
- 	  sym_len = 0;
-	  sym_name = NULL;	/* pacify "gcc -Werror" */
- 	  if (psymtab_language == language_cplus)
- 	    {
- 	      char *new_name, *name = xmalloc (p - namestring + 1);
- 	      memcpy (name, namestring, p - namestring);
- 	      name[p - namestring] = '\0';
- 	      new_name = cp_canonicalize_string (name);
- 	      if (new_name != NULL)
- 		{
- 		  sym_len = strlen (new_name);
- 		  sym_name = obsavestring (new_name, sym_len,
- 					   &objfile->objfile_obstack);
- 		  xfree (new_name);
- 		}
-              xfree (name);
- 	    }
+	  case ':':
+	    /* It is a C++ nested symbol.  We don't need to record it
+	       (I don't think); if we try to look up foo::bar::baz,
+	       then symbols for the symtab containing foo should get
+	       read in, I think.  */
+	    /* Someone says sun cc puts out symbols like
+	       /foo/baz/maclib::/usr/local/bin/maclib,
+	       which would get here with a symbol type of ':'.  */
+	    continue;
 
- 	  if (sym_len == 0)
- 	    {
- 	      sym_name = namestring;
- 	      sym_len = p - namestring;
- 	    }
+	  default:
+	    /* Unexpected symbol descriptor.  The second and subsequent stabs
+	       of a continued stab can show up here.  The question is
+	       whether they ever can mimic a normal stab--it would be
+	       nice if not, since we certainly don't want to spend the
+	       time searching to the end of every string looking for
+	       a backslash.  */
+
+	    complaint (&symfile_complaints, _("unknown symbol descriptor `%c'"),
+		       p[1]);
+
+	    /* Ignore it; perhaps it is an extension that we don't
+	       know about.  */
+	    continue;
+	  }
+      }
 
-	  /* Main processing section for debugging symbols which
-	     the initial read through the symbol tables needs to worry
-	     about.  If we reach this point, the symbol which we are
-	     considering is definitely one we are interested in.
-	     p must also contain the (valid) index into the namestring
-	     which indicates the debugging type symbol.  */
+      case N_EXCL:
 
-	  switch (p[1])
-	    {
-	    case 'S':
-	      nlist.n_value += ANOFFSET (objfile->section_offsets,
-					 data_sect_index);
-
-	      if (gdbarch_static_transform_name_p (gdbarch))
-		namestring = gdbarch_static_transform_name (gdbarch,
-							    namestring);
-
-	      add_psymbol_to_list (sym_name, sym_len, 1,
-				   VAR_DOMAIN, LOC_STATIC,
-				   &objfile->static_psymbols,
-				   0, nlist.n_value,
-				   psymtab_language, objfile);
-	      continue;
+	namestring = set_namestring (objfile, &nlist);
 
-	    case 'G':
-	      nlist.n_value += ANOFFSET (objfile->section_offsets,
-					 data_sect_index);
-	      /* The addresses in these entries are reported to be
-		 wrong.  See the code that reads 'G's for symtabs. */
-	      add_psymbol_to_list (sym_name, sym_len, 1,
-				   VAR_DOMAIN, LOC_STATIC,
-				   &objfile->global_psymbols,
-				   0, nlist.n_value,
-				   psymtab_language, objfile);
-	      continue;
+	/* Find the corresponding bincl and mark that psymtab on the
+	   psymtab dependency list */
+	{
+	  struct partial_symtab *needed_pst =
+	    find_corresponding_bincl_psymtab (namestring, nlist.n_value);
 
-	    case 'T':
-	      /* When a 'T' entry is defining an anonymous enum, it
-		 may have a name which is the empty string, or a
-		 single space.  Since they're not really defining a
-		 symbol, those shouldn't go in the partial symbol
-		 table.  We do pick up the elements of such enums at
-		 'check_enum:', below.  */
-	      if (p >= namestring + 2
-		  || (p == namestring + 1
-		      && namestring[0] != ' '))
-		{
-		  add_psymbol_to_list (sym_name, sym_len, 1,
-				       STRUCT_DOMAIN, LOC_TYPEDEF,
-				       &objfile->static_psymbols,
-				       nlist.n_value, 0,
-				       psymtab_language, objfile);
-		  if (p[2] == 't')
-		    {
-		      /* Also a typedef with the same name.  */
-		      add_psymbol_to_list (sym_name, sym_len, 1,
-					   VAR_DOMAIN, LOC_TYPEDEF,
-					   &objfile->static_psymbols,
-					   nlist.n_value, 0,
-					   psymtab_language, objfile);
-		      p += 1;
-		    }
-		}
-	      goto check_enum;
+	  /* If this include file was defined earlier in this file,
+	     leave it alone.  */
+	  if (needed_pst == pst)
+	    continue;
 
-	    case 't':
-	      if (p != namestring)	/* a name is there, not just :T... */
-		{
-		  add_psymbol_to_list (sym_name, sym_len, 1,
-				       VAR_DOMAIN, LOC_TYPEDEF,
-				       &objfile->static_psymbols,
-				       nlist.n_value, 0,
-				       psymtab_language, objfile);
-		}
-	    check_enum:
-	      /* If this is an enumerated type, we need to
-		 add all the enum constants to the partial symbol
-		 table.  This does not cover enums without names, e.g.
-		 "enum {a, b} c;" in C, but fortunately those are
-		 rare.  There is no way for GDB to find those from the
-		 enum type without spending too much time on it.  Thus
-		 to solve this problem, the compiler needs to put out the
-		 enum in a nameless type.  GCC2 does this.  */
-
-	      /* We are looking for something of the form
-		 <name> ":" ("t" | "T") [<number> "="] "e"
-		 {<constant> ":" <value> ","} ";".  */
-
-	      /* Skip over the colon and the 't' or 'T'.  */
-	      p += 2;
-	      /* This type may be given a number.  Also, numbers can come
-		 in pairs like (0,26).  Skip over it.  */
-	      while ((*p >= '0' && *p <= '9')
-		     || *p == '(' || *p == ',' || *p == ')'
-		     || *p == '=')
-		p++;
-
-	      if (*p++ == 'e')
-		{
-		  /* The aix4 compiler emits extra crud before the members.  */
-		  if (*p == '-')
-		    {
-		      /* Skip over the type (?).  */
-		      while (*p != ':')
-			p++;
-
-		      /* Skip over the colon.  */
-		      p++;
-		    }
-
-		  /* We have found an enumerated type.  */
-		  /* According to comments in read_enum_type
-		     a comma could end it instead of a semicolon.
-		     I don't know where that happens.
-		     Accept either.  */
-		  while (*p && *p != ';' && *p != ',')
-		    {
-		      char *q;
-
-		      /* Check for and handle cretinous dbx symbol name
-			 continuation!  */
-		      if (*p == '\\' || (*p == '?' && p[1] == '\0'))
-			p = next_symbol_text (objfile);
-
-		      /* Point to the character after the name
-			 of the enum constant.  */
-		      for (q = p; *q && *q != ':'; q++)
-			;
-		      /* Note that the value doesn't matter for
-			 enum constants in psymtabs, just in symtabs.  */
-		      add_psymbol_to_list (p, q - p, 1,
-					   VAR_DOMAIN, LOC_CONST,
-					   &objfile->static_psymbols, 0,
-					   0, psymtab_language, objfile);
-		      /* Point past the name.  */
-		      p = q;
-		      /* Skip over the value.  */
-		      while (*p && *p != ',')
-			p++;
-		      /* Advance past the comma.  */
-		      if (*p)
-			p++;
-		    }
-		}
-	      continue;
+	  if (needed_pst)
+	    {
+	      int i;
+	      int found = 0;
 
-	    case 'c':
-	      /* Constant, e.g. from "const" in Pascal.  */
-	      add_psymbol_to_list (sym_name, sym_len, 1,
-				   VAR_DOMAIN, LOC_CONST,
-				   &objfile->static_psymbols, nlist.n_value,
-				   0, psymtab_language, objfile);
-	      continue;
+	      for (i = 0; i < dependencies_used; i++)
+		if (dependency_list[i] == needed_pst)
+		  {
+		    found = 1;
+		    break;
+		  }
 
-	    case 'f':
-	      if (! pst)
-		{
-		  int name_len = p - namestring;
-		  char *name = xmalloc (name_len + 1);
-		  memcpy (name, namestring, name_len);
-		  name[name_len] = '\0';
-		  function_outside_compilation_unit_complaint (name);
-		  xfree (name);
-		}
-	      nlist.n_value += ANOFFSET (objfile->section_offsets, 
-					 SECT_OFF_TEXT (objfile));
-	      /* Kludges for ELF/STABS with Sun ACC */
-	      last_function_name = namestring;
-	      /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
-		 value for the bottom of the text seg in those cases. */
-	      if (nlist.n_value == ANOFFSET (objfile->section_offsets, 
-					     SECT_OFF_TEXT (objfile))
-		  && gdbarch_sofun_address_maybe_missing (gdbarch))
-		{
-		  CORE_ADDR minsym_valu = 
-		    find_stab_function_addr (namestring, 
-					     pst ? pst->filename : NULL, 
-					     objfile);
-		  /* find_stab_function_addr will return 0 if the minimal
-		     symbol wasn't found.  (Unfortunately, this might also
-		     be a valid address.)  Anyway, if it *does* return 0,
-		     it is likely that the value was set correctly to begin
-		     with... */
-		  if (minsym_valu != 0)
-		    nlist.n_value = minsym_valu;
-		}
-	      if (pst && textlow_not_set
-		  && gdbarch_sofun_address_maybe_missing (gdbarch))
-		{
-		  pst->textlow = nlist.n_value;
-		  textlow_not_set = 0;
-		}
-	      /* End kludge.  */
-
-	      /* Keep track of the start of the last function so we
-		 can handle end of function symbols.  */
-	      last_function_start = nlist.n_value;
-
-	      /* In reordered executables this function may lie outside
-		 the bounds created by N_SO symbols.  If that's the case
-		 use the address of this function as the low bound for
-		 the partial symbol table.  */
-	      if (pst
-		  && (textlow_not_set
-		      || (nlist.n_value < pst->textlow
-			  && (nlist.n_value
-			      != ANOFFSET (objfile->section_offsets,
-					   SECT_OFF_TEXT (objfile))))))
-		{
-		  pst->textlow = nlist.n_value;
-		  textlow_not_set = 0;
-		}
-	      add_psymbol_to_list (sym_name, sym_len, 1,
-				   VAR_DOMAIN, LOC_BLOCK,
-				   &objfile->static_psymbols,
-				   0, nlist.n_value,
-				   psymtab_language, objfile);
-	      continue;
+	      /* If it's already in the list, skip the rest.  */
+	      if (found)
+		continue;
 
-	      /* Global functions were ignored here, but now they
-		 are put into the global psymtab like one would expect.
-		 They're also in the minimal symbol table.  */
-	    case 'F':
-	      if (! pst)
+	      dependency_list[dependencies_used++] = needed_pst;
+	      if (dependencies_used >= dependencies_allocated)
 		{
-		  int name_len = p - namestring;
-		  char *name = xmalloc (name_len + 1);
-		  memcpy (name, namestring, name_len);
-		  name[name_len] = '\0';
-		  function_outside_compilation_unit_complaint (name);
-		  xfree (name);
-		}
-	      nlist.n_value += ANOFFSET (objfile->section_offsets, 
-					 SECT_OFF_TEXT (objfile));
-	      /* Kludges for ELF/STABS with Sun ACC */
-	      last_function_name = namestring;
-	      /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
-		 value for the bottom of the text seg in those cases. */
-	      if (nlist.n_value == ANOFFSET (objfile->section_offsets, 
-					     SECT_OFF_TEXT (objfile))
-		  && gdbarch_sofun_address_maybe_missing (gdbarch))
-		{
-		  CORE_ADDR minsym_valu = 
-		    find_stab_function_addr (namestring, 
-					     pst ? pst->filename : NULL, 
-					     objfile);
-		  /* find_stab_function_addr will return 0 if the minimal
-		     symbol wasn't found.  (Unfortunately, this might also
-		     be a valid address.)  Anyway, if it *does* return 0,
-		     it is likely that the value was set correctly to begin
-		     with... */
-		  if (minsym_valu != 0)
-		    nlist.n_value = minsym_valu;
-		}
-	      if (pst && textlow_not_set
-		  && gdbarch_sofun_address_maybe_missing (gdbarch))
-		{
-		  pst->textlow = nlist.n_value;
-		  textlow_not_set = 0;
-		}
-	      /* End kludge.  */
-
-	      /* Keep track of the start of the last function so we
-		 can handle end of function symbols.  */
-	      last_function_start = nlist.n_value;
-
-	      /* In reordered executables this function may lie outside
-		 the bounds created by N_SO symbols.  If that's the case
-		 use the address of this function as the low bound for
-		 the partial symbol table.  */
-	      if (pst
-		  && (textlow_not_set
-		      || (nlist.n_value < pst->textlow
-			  && (nlist.n_value
-			      != ANOFFSET (objfile->section_offsets,
-					   SECT_OFF_TEXT (objfile))))))
-		{
-		  pst->textlow = nlist.n_value;
-		  textlow_not_set = 0;
+		  struct partial_symtab **orig = dependency_list;
+		  dependency_list =
+		    (struct partial_symtab **)
+		    alloca ((dependencies_allocated *= 2)
+			    * sizeof (struct partial_symtab *));
+		  memcpy (dependency_list, orig,
+			  (dependencies_used
+			   * sizeof (struct partial_symtab *)));
+#ifdef DEBUG_INFO
+		  fprintf_unfiltered (gdb_stderr,
+				      "Had to reallocate dependency list.\n");
+		  fprintf_unfiltered (gdb_stderr,
+				      "New dependencies allocated: %d\n",
+				      dependencies_allocated);
+#endif
 		}
-	      add_psymbol_to_list (sym_name, sym_len, 1,
-				   VAR_DOMAIN, LOC_BLOCK,
-				   &objfile->global_psymbols,
-				   0, nlist.n_value,
-				   psymtab_language, objfile);
-	      continue;
-
-	      /* Two things show up here (hopefully); static symbols of
-		 local scope (static used inside braces) or extensions
-		 of structure symbols.  We can ignore both.  */
-	    case 'V':
-	    case '(':
-	    case '0':
-	    case '1':
-	    case '2':
-	    case '3':
-	    case '4':
-	    case '5':
-	    case '6':
-	    case '7':
-	    case '8':
-	    case '9':
-	    case '-':
-	    case '#':	/* for symbol identification (used in live ranges) */
-	      continue;
-
-	    case ':':
-	      /* It is a C++ nested symbol.  We don't need to record it
-		 (I don't think); if we try to look up foo::bar::baz,
-		 then symbols for the symtab containing foo should get
-		 read in, I think.  */
-	      /* Someone says sun cc puts out symbols like
-		 /foo/baz/maclib::/usr/local/bin/maclib,
-		 which would get here with a symbol type of ':'.  */
-	      continue;
-
-	    default:
-	      /* Unexpected symbol descriptor.  The second and subsequent stabs
-		 of a continued stab can show up here.  The question is
-		 whether they ever can mimic a normal stab--it would be
-		 nice if not, since we certainly don't want to spend the
-		 time searching to the end of every string looking for
-		 a backslash.  */
-
-	      complaint (&symfile_complaints, _("unknown symbol descriptor `%c'"),
-			 p[1]);
-
-	      /* Ignore it; perhaps it is an extension that we don't
-		 know about.  */
-	      continue;
 	    }
 	}
-
-	case N_EXCL:
-
-	  namestring = set_namestring (objfile, &nlist);
-
-	  /* Find the corresponding bincl and mark that psymtab on the
-	     psymtab dependency list */
+	continue;
+
+      case N_ENDM:
+	/* Solaris 2 end of module, finish current partial symbol table.
+	   end_psymtab will set pst->texthigh to the proper value, which
+	   is necessary if a module compiled without debugging info
+	   follows this module.  */
+	if (pst && gdbarch_sofun_address_maybe_missing (gdbarch))
 	  {
-	    struct partial_symtab *needed_pst =
-	      find_corresponding_bincl_psymtab (namestring, nlist.n_value);
-
-	    /* If this include file was defined earlier in this file,
-	       leave it alone.  */
-	    if (needed_pst == pst)
-	      continue;
-
-	    if (needed_pst)
-	      {
-		int i;
-		int found = 0;
-
-		for (i = 0; i < dependencies_used; i++)
-		  if (dependency_list[i] == needed_pst)
-		    {
-		      found = 1;
-		      break;
-		    }
-
-		/* If it's already in the list, skip the rest.  */
-		if (found)
-		  continue;
-
-		dependency_list[dependencies_used++] = needed_pst;
-		if (dependencies_used >= dependencies_allocated)
-		  {
-		    struct partial_symtab **orig = dependency_list;
-		    dependency_list =
-		      (struct partial_symtab **)
-		      alloca ((dependencies_allocated *= 2)
-			      * sizeof (struct partial_symtab *));
-		    memcpy (dependency_list, orig,
-			    (dependencies_used
-			     * sizeof (struct partial_symtab *)));
-#ifdef DEBUG_INFO
-		    fprintf_unfiltered (gdb_stderr,
-					"Had to reallocate dependency list.\n");
-		    fprintf_unfiltered (gdb_stderr,
-					"New dependencies allocated: %d\n",
-					dependencies_allocated);
-#endif
-		  }
-	      }
+	    end_psymtab (pst, psymtab_include_list, includes_used,
+			 symnum * symbol_size,
+			 (CORE_ADDR) 0,
+			 dependency_list, dependencies_used, textlow_not_set);
+	    pst = (struct partial_symtab *) 0;
+	    includes_used = 0;
+	    dependencies_used = 0;
+	    has_line_numbers = 0;
 	  }
-	  continue;
+	continue;
 
-	case N_ENDM:
-	  /* Solaris 2 end of module, finish current partial symbol table.
-	     end_psymtab will set pst->texthigh to the proper value, which
-	     is necessary if a module compiled without debugging info
-	     follows this module.  */
-	  if (pst && gdbarch_sofun_address_maybe_missing (gdbarch))
-	    {
-	      end_psymtab (pst, psymtab_include_list, includes_used,
-			   symnum * symbol_size,
-			   (CORE_ADDR) 0,
-			   dependency_list, dependencies_used, textlow_not_set);
-	      pst = (struct partial_symtab *) 0;
-	      includes_used = 0;
-	      dependencies_used = 0;
-	      has_line_numbers = 0;
-	    }
-	  continue;
-
-	case N_RBRAC:
+      case N_RBRAC:
 #ifdef HANDLE_RBRAC
-	  HANDLE_RBRAC (nlist.n_value);
-	  continue;
+	HANDLE_RBRAC (nlist.n_value);
+	continue;
 #endif
-	case N_EINCL:
-	case N_DSLINE:
-	case N_BSLINE:
-	case N_SSYM:		/* Claim: Structure or union element.
-				   Hopefully, I can ignore this.  */
-	case N_ENTRY:		/* Alternate entry point; can ignore. */
-	case N_MAIN:		/* Can definitely ignore this.   */
-	case N_CATCH:		/* These are GNU C++ extensions */
-	case N_EHDECL:		/* that can safely be ignored here. */
-	case N_LENG:
-	case N_BCOMM:
-	case N_ECOMM:
-	case N_ECOML:
-	case N_FNAME:
-	case N_SLINE:
-	case N_RSYM:
-	case N_PSYM:
-	case N_LBRAC:
-	case N_NSYMS:		/* Ultrix 4.0: symbol count */
-	case N_DEFD:		/* GNU Modula-2 */
-	case N_ALIAS:		/* SunPro F77: alias name, ignore for now.  */
-
-	case N_OBJ:		/* useless types from Solaris */
-	case N_OPT:
-	case N_PATCH:
-	  /* These symbols aren't interesting; don't worry about them */
-
-	  continue;
-
-	default:
-	  /* If we haven't found it yet, ignore it.  It's probably some
-	     new type we don't know about yet.  */
-	  unknown_symtype_complaint (hex_string (nlist.n_type));
-	  continue;
-	}
-    }
+      case N_EINCL:
+      case N_DSLINE:
+      case N_BSLINE:
+      case N_SSYM:		/* Claim: Structure or union element.
+				 Hopefully, I can ignore this.  */
+      case N_ENTRY:		/* Alternate entry point; can ignore. */
+      case N_MAIN:		/* Can definitely ignore this.   */
+      case N_CATCH:		/* These are GNU C++ extensions */
+      case N_EHDECL:		/* that can safely be ignored here. */
+      case N_LENG:
+      case N_BCOMM:
+      case N_ECOMM:
+      case N_ECOML:
+      case N_FNAME:
+      case N_SLINE:
+      case N_RSYM:
+      case N_PSYM:
+      case N_LBRAC:
+      case N_NSYMS:		/* Ultrix 4.0: symbol count */
+      case N_DEFD:		/* GNU Modula-2 */
+      case N_ALIAS:		/* SunPro F77: alias name, ignore for now.  */
+
+      case N_OBJ:		/* useless types from Solaris */
+      case N_OPT:
+      case N_PATCH:
+	/* These symbols aren't interesting; don't worry about them */
+
+	continue;
+
+      default:
+	/* If we haven't found it yet, ignore it.  It's probably some
+	   new type we don't know about yet.  */
+	unknown_symtype_complaint (hex_string (nlist.n_type));
+	continue;
+      }
+  }
 
-  /* If there's stuff to be cleaned up, clean it up.  */
-  if (pst)
-    {
-      /* Don't set pst->texthigh lower than it already is.  */
-      CORE_ADDR text_end =
-	(lowest_text_address == (CORE_ADDR) -1
-	 ? (text_addr + ANOFFSET (objfile->section_offsets,
-				  SECT_OFF_TEXT (objfile)))
+/* If there's stuff to be cleaned up, clean it up.  */
+if (pst)
+  {
+    /* Don't set pst->texthigh lower than it already is.  */
+    CORE_ADDR text_end =
+      (lowest_text_address == addr_minus_one (gdbarch)
+	 ? addr_add_offset (gdbarch, text_addr,
+			    ANOFFSET (objfile->section_offsets,
+				      SECT_OFF_TEXT (objfile)))
 	 : lowest_text_address)
 	+ text_size;
 
@@ -2723,7 +2742,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
      other than Solaris 2, this just holds the SECT_OFF_TEXT value,
      and is used to relocate these symbol types rather than
      SECTION_OFFSETS.  */
-  static CORE_ADDR function_start_offset;
+  static addr_offset_t function_start_offset;
 
   /* This holds the address of the start of a function, without the
      system peculiarities of function_start_offset.  */
@@ -2807,7 +2826,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 	  /* May be switching to an assembler file which may not be using
 	     block relative stabs, so reset the offset.  */
 	  if (block_address_function_relative)
-	    function_start_offset = 0;
+	    function_start_offset.a = 0;
 
 	  break;
 	}
@@ -2815,7 +2834,9 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
       sline_found_in_function = 0;
 
       /* Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
       valu = gdbarch_smash_text_address (gdbarch, valu);
       last_function_start = valu;
 
@@ -2831,7 +2852,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 
       if (block_address_function_relative)
 	/* Relocate for Sun ELF acc fn-relative syms.  */
-	valu += function_start_offset;
+	valu = addr_add_offset (gdbarch, valu, function_start_offset);
       else
 	/* On most machines, the block addresses are relative to the
 	   N_SO, the linker did not relocate them (sigh).  */
@@ -2850,7 +2871,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 
       if (block_address_function_relative)
 	/* Relocate for Sun ELF acc fn-relative syms.  */
-	valu += function_start_offset;
+	valu = addr_add_offset (gdbarch, valu, function_start_offset);
       else
 	/* On most machines, the block addresses are relative to the
 	   N_SO, the linker did not relocate them (sigh).  */
@@ -2917,7 +2938,9 @@ no enclosing block"));
     case N_FN_SEQ:
       /* This kind of symbol indicates the start of an object file.
          Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
       break;
 
     case N_SO:
@@ -2925,7 +2948,9 @@ no enclosing block"));
          source file.  Finish the symbol table of the previous source
          file (if any) and start accumulating a new symbol table.
          Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
 
       n_opt_found = 0;
 
@@ -2950,7 +2975,7 @@ no enclosing block"));
 	break;
 
       if (block_address_function_relative)
-	function_start_offset = 0;
+	function_start_offset.a = 0;
 
       start_stabs ();
       start_symtab (name, NULL, valu);
@@ -2962,7 +2987,9 @@ no enclosing block"));
          sub-source-file, one whose contents were copied or included
          in the compilation of the main source file (whose name was
          given in the N_SO symbol).  Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
       start_subfile (name, current_subfile->dirname);
       break;
 
@@ -2987,7 +3014,7 @@ no enclosing block"));
 
       /* Relocate for dynamic loading and for ELF acc
          function-relative symbols.  */
-      valu += function_start_offset;
+      valu = addr_add_offset (gdbarch, valu, function_start_offset);
 
       /* GCC 2.95.3 emits the first N_SLINE stab somwehere in the
 	 middle of the prologue instead of right at the start of the
@@ -3066,7 +3093,9 @@ no enclosing block"));
 		   elfstab_offset_sections ever starts dealing with
 		   the text offset, and we still need to do this, we
 		   need to invent a SECT_OFF_ADDR_KLUDGE or something.  */
-		valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+		valu = addr_add_offset (gdbarch, valu,
+					ANOFFSET (section_offsets,
+						  SECT_OFF_TEXT (objfile)));
 		goto define_a_symbol;
 	      }
 	  }
@@ -3088,22 +3117,30 @@ no enclosing block"));
 
     case_N_STSYM:		/* Static symbol in data segment.  */
     case N_DSLINE:		/* Source line number, data segment.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_DATA (objfile)));
       goto define_a_symbol;
 
     case_N_LCSYM:		/* Static symbol in BSS segment.  */
     case N_BSLINE:		/* Source line number, BSS segment.  */
       /* N_BROWS: overlaps with N_BSLINE.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_BSS (objfile)));
       goto define_a_symbol;
 
     case_N_ROSYM:		/* Static symbol in read-only data segment.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_RODATA (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_RODATA (objfile)));
       goto define_a_symbol;
 
     case N_ENTRY:		/* Alternate entry point.  */
       /* Relocate for dynamic loading.  */
-      valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+      valu = addr_add_offset (gdbarch, valu,
+			      ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
       goto define_a_symbol;
 
       /* The following symbol types we don't know how to process.
@@ -3155,8 +3192,9 @@ no enclosing block"));
 	      /* Deal with the SunPRO 3.0 compiler which omits the
 	         address from N_FUN symbols.  */
 	      if (type == N_FUN
-		  && valu == ANOFFSET (section_offsets,
-				       SECT_OFF_TEXT (objfile))
+		  && addr_sub_offset (gdbarch, valu,
+				      ANOFFSET (section_offsets,
+						SECT_OFF_TEXT (objfile))) == 0
 		  && gdbarch_sofun_address_maybe_missing (gdbarch))
 		{
 		  CORE_ADDR minsym_valu = 
@@ -3179,7 +3217,7 @@ no enclosing block"));
 		   Solaris 2, these addresses are just absolute, or
 		   relative to the N_SO, depending on
 		   BLOCK_ADDRESS_ABSOLUTE.  */
-		function_start_offset = valu;
+		function_start_offset = addr_to_offset (gdbarch, valu);
 
 	      within_function = 1;
 
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -101,8 +101,11 @@ typedef bfd_byte gdb_byte;
 /* An address in the program being debugged.  Host byte order.  */
 typedef bfd_vma CORE_ADDR;
 
-/* The largest CORE_ADDR value.  */
-#define CORE_ADDR_MAX (~ (CORE_ADDR) 0)
+typedef struct
+  {
+    CORE_ADDR a;
+  }
+addr_offset_t;
 
 /* This is to make sure that LONGEST is at least as big as CORE_ADDR.  */
 
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -439,8 +439,9 @@ execute_cfa_program (struct dwarf2_fde *fde, gdb_byte *insn_ptr,
 					   fde->cie->addr_size, insn_ptr,
 					   &bytes_read, fde->initial_location);
 	      /* Apply the objfile offset for relocatable objects.  */
-	      fs->pc += ANOFFSET (fde->cie->unit->objfile->section_offsets,
-				  SECT_OFF_TEXT (fde->cie->unit->objfile));
+	      fs->pc = addr_add_offset (gdbarch, fs->pc,
+			    ANOFFSET (fde->cie->unit->objfile->section_offsets,
+				      SECT_OFF_TEXT (fde->cie->unit->objfile)));
 	      insn_ptr += bytes_read;
 	      break;
 
@@ -1577,9 +1578,10 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
 
   ALL_OBJFILES (objfile)
     {
+      struct gdbarch *gdbarch = get_objfile_arch (objfile);
       struct dwarf2_fde_table *fde_table;
       struct dwarf2_fde **p_fde;
-      CORE_ADDR offset;
+      addr_offset_t offset;
       CORE_ADDR seek_pc;
 
       fde_table = objfile_data (objfile, dwarf2_frame_objfile_data);
@@ -1590,15 +1592,17 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
       offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       gdb_assert (fde_table->num_entries > 0);
-      if (*pc < offset + fde_table->entries[0]->initial_location)
+      if (*pc < addr_add_offset (gdbarch,
+				 fde_table->entries[0]->initial_location,
+				 offset))
         continue;
 
-      seek_pc = *pc - offset;
+      seek_pc = addr_sub_offset (gdbarch, *pc, offset);
       p_fde = bsearch (&seek_pc, fde_table->entries, fde_table->num_entries,
                        sizeof (fde_table->entries[0]), bsearch_fde_cmp);
       if (p_fde != NULL)
         {
-          *pc = (*p_fde)->initial_location + offset;
+          *pc = addr_add_offset (gdbarch, (*p_fde)->initial_location, offset);
           return *p_fde;
         }
     }
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -67,9 +67,10 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
   unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu);
   CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Adjust base_address for relocatable objects.  */
-  CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets,
-				    SECT_OFF_TEXT (objfile));
-  CORE_ADDR base_address = baton->base_address + base_offset;
+  addr_offset_t base_offset = ANOFFSET (objfile->section_offsets,
+					SECT_OFF_TEXT (objfile));
+  CORE_ADDR base_address = addr_add_offset (gdbarch, baton->base_address,
+					    base_offset);
 
   loc_ptr = baton->data;
   buf_end = baton->data + baton->size;
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -967,7 +967,7 @@ static void get_scope_pc_bounds (struct die_info *,
 				 struct dwarf2_cu *);
 
 static void dwarf2_record_block_ranges (struct die_info *, struct block *,
-                                        CORE_ADDR, struct dwarf2_cu *);
+                                        addr_offset_t, struct dwarf2_cu *);
 
 static void dwarf2_add_field (struct field_info *, struct die_info *,
 			      struct dwarf2_cu *);
@@ -1865,11 +1865,12 @@ process_psymtab_comp_unit (struct objfile *objfile,
 			   gdb_byte *buffer, gdb_byte *info_ptr,
 			   unsigned int buffer_size)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = objfile->obfd;
   gdb_byte *beg_of_comp_unit = info_ptr;
   struct die_info *comp_unit_die;
   struct partial_symtab *pst;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
   struct cleanup *back_to_inner;
   struct dwarf2_cu cu;
   unsigned int bytes_read;
@@ -1975,8 +1976,9 @@ process_psymtab_comp_unit (struct objfile *objfile,
     /* 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);
+		       addr_add_offset (gdbarch, best_lowpc, baseaddr),
+		       addr_add_offset (gdbarch, best_highpc - 1, baseaddr),
+		       pst);
 
   /* Check if comp unit has_children.
      If so, read the rest of the partial symbols from this comp unit.
@@ -1986,7 +1988,7 @@ process_psymtab_comp_unit (struct objfile *objfile,
       struct partial_die_info *first_die;
       CORE_ADDR lowpc, highpc;
 
-      lowpc = ((CORE_ADDR) -1);
+      lowpc = addr_minus_one (gdbarch);
       highpc = ((CORE_ADDR) 0);
 
       first_die = load_partial_dies (abfd, buffer, info_ptr, 1, &cu);
@@ -1996,7 +1998,7 @@ process_psymtab_comp_unit (struct objfile *objfile,
 
       /* If we didn't find a lowpc, set it to highpc to avoid
 	 complaints from `maint check'.	 */
-      if (lowpc == ((CORE_ADDR) -1))
+      if (lowpc == addr_minus_one (gdbarch))
 	lowpc = highpc;
 
       /* If the compilation unit didn't have an explicit address range,
@@ -2007,8 +2009,8 @@ process_psymtab_comp_unit (struct objfile *objfile,
 	  best_highpc = highpc;
 	}
     }
-  pst->textlow = best_lowpc + baseaddr;
-  pst->texthigh = best_highpc + baseaddr;
+  pst->textlow = addr_add_offset (gdbarch, best_lowpc, baseaddr);
+  pst->texthigh = addr_add_offset (gdbarch, best_highpc, baseaddr);
 
   pst->n_global_syms = objfile->global_psymbols.next -
     (objfile->global_psymbols.list + pst->globals_offset);
@@ -2078,6 +2080,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 {
   /* Instead of reading this into a big buffer, we should probably use
      mmap()  on architectures that support it. (FIXME) */
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = objfile->obfd;
   gdb_byte *info_ptr;
   struct cleanup *back_to;
@@ -2093,7 +2096,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
   create_all_comp_units (objfile);
 
   objfile->psymtabs_addrmap =
-    addrmap_create_mutable (&objfile->objfile_obstack);
+    addrmap_create_mutable (gdbarch, &objfile->objfile_obstack);
 
   /* Since the objects we're extracting from .debug_info vary in
      length, only the individual functions to extract them (like
@@ -2432,11 +2435,12 @@ 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;
   char *actual_name = NULL;
   const char *my_prefix;
   const struct partial_symbol *psym = NULL;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
   int built_actual_name = 0;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
@@ -2460,24 +2464,30 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
              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_add_offset (gdbarch, pdi->lowpc,
+							 baseaddr),
+					mst_text, objfile); */
 	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 				      built_actual_name,
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->global_psymbols,
-				      0, pdi->lowpc + baseaddr,
+				      0, addr_add_offset (gdbarch, pdi->lowpc,
+							  baseaddr),
 				      cu->language, objfile);
 	}
       else
 	{
-	  /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
-	     mst_file_text, objfile); */
+	  /*prim_record_minimal_symbol (actual_name,
+					addr_add_offset (gdbarch, pdi->lowpc,
+							 baseaddr),
+					mst_file_text, objfile); */
 	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 				      built_actual_name,
 				      VAR_DOMAIN, LOC_BLOCK,
 				      &objfile->static_psymbols,
-				      0, pdi->lowpc + baseaddr,
+				      0, addr_add_offset (gdbarch, pdi->lowpc,
+							  baseaddr),
 				      cu->language, objfile);
 	}
       break;
@@ -2504,7 +2514,8 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 					built_actual_name,
 					VAR_DOMAIN, LOC_STATIC,
 					&objfile->global_psymbols,
-					0, addr + baseaddr,
+					0, addr_add_offset (gdbarch, addr,
+							    baseaddr),
 					cu->language, objfile);
 	}
       else
@@ -2517,13 +2528,16 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 	      return;
 	    }
 	  addr = decode_locdesc (pdi->locdesc, cu);
-	  /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
-	     mst_file_data, objfile); */
+	  /*prim_record_minimal_symbol (actual_name,
+					addr_add_offset (gdbarch, addr,
+							 baseaddr),
+					mst_file_data, objfile); */
 	  psym = add_psymbol_to_list (actual_name, strlen (actual_name),
 				      built_actual_name,
 				      VAR_DOMAIN, LOC_STATIC,
 				      &objfile->static_psymbols,
-				      0, addr + baseaddr,
+				      0, addr_add_offset (gdbarch, addr,
+							  baseaddr),
 				      cu->language, objfile);
 	}
       break;
@@ -2689,11 +2703,8 @@ add_partial_subprogram (struct partial_die_info *pdi,
             *highpc = pdi->highpc;
 	  if (need_pc)
 	    {
-	      CORE_ADDR baseaddr;
 	      struct objfile *objfile = cu->objfile;
 
-	      baseaddr = ANOFFSET (objfile->section_offsets,
-				   SECT_OFF_TEXT (objfile));
 	      addrmap_set_empty (objfile->psymtabs_addrmap,
 				 pdi->lowpc, pdi->highpc - 1,
 				 cu->per_cu->psymtab);
@@ -3218,11 +3229,12 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
   struct partial_symtab *pst = per_cu->psymtab;
   struct dwarf2_cu *cu = per_cu->cu;
   struct objfile *objfile = pst->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = objfile->obfd;
   CORE_ADDR lowpc, highpc;
   struct symtab *symtab;
   struct cleanup *back_to;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
@@ -3241,7 +3253,8 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
      it, by scanning the DIE's below the compilation unit.  */
   get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
 
-  symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
+  symtab = end_symtab (addr_add_offset (gdbarch, highpc, baseaddr), objfile,
+                       SECT_OFF_TEXT (objfile));
 
   /* Set symtab language to language from DW_AT_language.
      If the compilation is from a C file generated by language preprocessors,
@@ -3487,9 +3500,10 @@ static void
 read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct comp_unit_head *cu_header = &cu->header;
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-  CORE_ADDR lowpc = ((CORE_ADDR) -1);
+  CORE_ADDR lowpc = addr_minus_one (gdbarch);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
   struct attribute *attr;
   char *name = NULL;
@@ -3497,7 +3511,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
   struct die_info *child_die;
   bfd *abfd = objfile->obfd;
   struct line_header *line_header = 0;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
   
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
@@ -3505,10 +3519,10 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   /* If we didn't find a lowpc, set it to highpc to avoid complaints
      from finish_block.  */
-  if (lowpc == ((CORE_ADDR) -1))
+  if (lowpc == addr_minus_one (gdbarch))
     lowpc = highpc;
-  lowpc += baseaddr;
-  highpc += baseaddr;
+  lowpc = addr_add_offset (gdbarch, lowpc, baseaddr);
+  highpc = addr_add_offset (gdbarch, highpc, baseaddr);
 
   /* Find the filename.  Do not use dwarf2_name here, since the filename
      is not a source language identifier.  */
@@ -3610,6 +3624,7 @@ static void
 read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
   CORE_ADDR lowpc;
   struct attribute *attr;
@@ -3621,7 +3636,8 @@ read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   /* start_symtab needs a low pc, but we don't really have one.
      Do what read_file_scope would do in the absence of such info.  */
-  lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+  lowpc = addr_add_offset (gdbarch, 0, ANOFFSET (objfile->section_offsets,
+                                                 SECT_OFF_TEXT (objfile)));
 
   /* Find the filename.  Do not use dwarf2_name here, since the filename
      is not a source language identifier.  */
@@ -3824,13 +3840,14 @@ 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;
   struct die_info *child_die;
   struct attribute *attr, *call_line, *call_file;
   char *name;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
   struct block *block;
   int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
 
@@ -3857,8 +3874,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
     return;
 
-  lowpc += baseaddr;
-  highpc += baseaddr;
+  lowpc = addr_add_offset (gdbarch, lowpc, baseaddr);
+  highpc = addr_add_offset (gdbarch, highpc, baseaddr);
 
   /* Record the function range for dwarf_decode_lines.  */
   add_to_cu_func_list (name, lowpc, highpc, cu);
@@ -3930,10 +3947,11 @@ 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;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
@@ -3944,8 +3962,8 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
      describe ranges.  */
   if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
     return;
-  lowpc += baseaddr;
-  highpc += baseaddr;
+  lowpc = addr_add_offset (gdbarch, lowpc, baseaddr);
+  highpc = addr_add_offset (gdbarch, highpc, baseaddr);
 
   push_context (0, lowpc);
   if (die->child != NULL)
@@ -3991,6 +4009,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
 		    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;
@@ -4004,7 +4023,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   int low_set;
   CORE_ADDR low = 0;
   CORE_ADDR high = 0;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
 
   found_base = cu->base_known;
   base = cu->base_address;
@@ -4075,7 +4094,8 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
 
       if (ranges_pst != NULL && range_beginning < range_end)
 	addrmap_set_empty (objfile->psymtabs_addrmap,
-			   range_beginning + baseaddr, range_end - 1 + baseaddr,
+			   addr_add_offset (gdbarch, range_beginning, baseaddr),
+			   addr_add_offset (gdbarch, range_end - 1, baseaddr),
 			   ranges_pst);
 
       /* FIXME: This is recording everything as a low-high
@@ -4215,7 +4235,8 @@ get_scope_pc_bounds (struct die_info *die,
 		     CORE_ADDR *lowpc, CORE_ADDR *highpc,
 		     struct dwarf2_cu *cu)
 {
-  CORE_ADDR best_low = (CORE_ADDR) -1;
+  struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
+  CORE_ADDR best_low = addr_minus_one (gdbarch);
   CORE_ADDR best_high = (CORE_ADDR) 0;
   CORE_ADDR current_low, current_high;
 
@@ -4245,7 +4266,7 @@ get_scope_pc_bounds (struct die_info *die,
 	       standards says that they have to be there.  */
 	    get_scope_pc_bounds (child, &current_low, &current_high, cu);
 
-	    if (current_low != ((CORE_ADDR) -1))
+	    if (current_low != addr_minus_one (gdbarch))
 	      {
 		best_low = min (best_low, current_low);
 		best_high = max (best_high, current_high);
@@ -4268,8 +4289,9 @@ get_scope_pc_bounds (struct die_info *die,
    in DIE.  */
 static void
 dwarf2_record_block_ranges (struct die_info *die, struct block *block,
-                            CORE_ADDR baseaddr, struct dwarf2_cu *cu)
+                            addr_offset_t baseaddr, struct dwarf2_cu *cu)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
   struct attribute *attr;
 
   attr = dwarf2_attr (die, DW_AT_high_pc, cu);
@@ -4280,7 +4302,10 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
       if (attr)
         {
           CORE_ADDR low = DW_ADDR (attr);
-          record_block_range (block, baseaddr + low, baseaddr + high - 1);
+
+          record_block_range (gdbarch, block,
+			      addr_add_offset (gdbarch, low, baseaddr),
+	                      addr_add_offset (gdbarch, high - 1, baseaddr));
         }
     }
 
@@ -4350,9 +4375,11 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
                   return;
                 }
 
-              record_block_range (block, 
-                                  baseaddr + base + start, 
-                                  baseaddr + base + end - 1);
+              record_block_range (gdbarch, block,
+                                  addr_add_offset (gdbarch, base + start,
+						   baseaddr),
+                                  addr_add_offset (gdbarch, base + end - 1,
+				                   baseaddr));
             }
         }
     }
@@ -7905,7 +7932,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
   gdb_byte *line_end;
   unsigned int bytes_read, extended_len;
   unsigned char op_code, extended_op, adj_opcode;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
   struct objfile *objfile = cu->objfile;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   const int decode_for_pst_p = (pst != NULL);
@@ -8000,7 +8027,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
 		case DW_LNE_set_address:
 		  address = read_address (abfd, line_ptr, cu, &bytes_read);
 		  line_ptr += bytes_read;
-		  address += baseaddr;
+		  address = addr_add_offset (gdbarch, address, baseaddr);
 		  break;
 		case DW_LNE_define_file:
                   {
@@ -8267,6 +8294,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
 		     struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct comp_unit_head *cu_header = &cu->header;
 
   /* NOTE drow/2003-01-30: There used to be a comment and some special
@@ -8302,8 +8330,10 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
 	read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
       SYMBOL_CLASS (sym) = LOC_STATIC;
       fixup_symbol_section (sym, objfile);
-      SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
-					      SYMBOL_SECTION (sym));
+      SYMBOL_VALUE_ADDRESS (sym) = addr_add_offset (gdbarch,
+						    SYMBOL_VALUE_ADDRESS (sym),
+					     ANOFFSET (objfile->section_offsets,
+						       SYMBOL_SECTION (sym)));
       return;
     }
 
@@ -8328,11 +8358,12 @@ static struct symbol *
 new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct symbol *sym = NULL;
   char *name;
   struct attribute *attr = NULL;
   struct attribute *attr2 = NULL;
-  CORE_ADDR baseaddr;
+  addr_offset_t baseaddr;
   int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
@@ -8392,9 +8423,9 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	case DW_TAG_label:
 	  attr = dwarf2_attr (die, DW_AT_low_pc, cu);
 	  if (attr)
-	    {
-	      SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
-	    }
+	    SYMBOL_VALUE_ADDRESS (sym) = addr_add_offset (gdbarch,
+							  DW_ADDR (attr),
+							  baseaddr);
 	  SYMBOL_CLASS (sym) = LOC_LABEL;
 	  break;
 	case DW_TAG_subprogram:
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -226,7 +226,7 @@ elf_symtab_read (struct objfile *objfile, int type,
   asymbol *sym;
   long i;
   CORE_ADDR symaddr;
-  CORE_ADDR offset;
+  addr_offset_t offset;
   enum minimal_symbol_type ms_type;
   /* If sectinfo is nonNULL, it contains section info that should end up
      filed in the objfile.  */
@@ -298,7 +298,9 @@ elf_symtab_read (struct objfile *objfile, int type,
 	  if (!sect)
 	    continue;
 
-	  symaddr += ANOFFSET (objfile->section_offsets, sect->index);
+	  symaddr = addr_add_offset (gdbarch, symaddr,
+				     ANOFFSET (objfile->section_offsets,
+					       sect->index));
 
 	  msym = record_minimal_symbol
 	    (sym->name, strlen (sym->name), copy_names,
@@ -343,9 +345,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 	     section offset.  */
 	  if (sym->section != &bfd_abs_section
 	      && !(sym->section->flags & SEC_THREAD_LOCAL))
-	    {
-	      symaddr += offset;
-	    }
+	    symaddr = addr_add_offset (gdbarch, symaddr, offset);
 	  /* For non-absolute symbols, use the type of the section
 	     they are relative to, to intuit text/data.  Bfd provides
 	     no way of figuring this out for absolute symbols. */
@@ -381,7 +381,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 		{
 		  if (sym->name[0] == '.')
 		    continue;
-		  symaddr += offset;
+		  symaddr = addr_add_offset (gdbarch, symaddr, offset);
 		}
 	    }
 	  else if (sym->section->flags & SEC_CODE)
@@ -483,7 +483,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 		      /* Relocate non-absolute symbols by the
 			 section offset.  */
 		      if (sym->section != &bfd_abs_section)
-			symaddr += offset;
+			symaddr = addr_add_offset (gdbarch, symaddr, offset);
 		      sectinfo->sections[special_local_sect] = symaddr;
 		      /* The special local symbols don't go in the
 			 minimal symbol table, so ignore this one.  */
@@ -991,6 +991,7 @@ elf_symfile_init (struct objfile *objfile)
 void
 elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   char *filename = pst->filename;
   struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
   struct stab_section_info *maybe = dbx->stab_section_info;
@@ -1034,7 +1035,8 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
 	obstack_alloc (&objfile->objfile_obstack, 
 		       SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
       for (i = 0; i < maybe->num_sections; i++)
-	(pst->section_offsets)->offsets[i] = maybe->sections[i];
+	(pst->section_offsets)->offsets[i] = addr_to_offset (gdbarch,
+							    maybe->sections[i]);
       return;
     }
 
--- a/gdb/findcmd.c
+++ b/gdb/findcmd.c
@@ -49,7 +49,7 @@ put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p)
    Parse the arguments of the "find" command.  */
 
 static void
-parse_find_args (char *args, ULONGEST *max_countp,
+parse_find_args (struct gdbarch *gdbarch, char *args, ULONGEST *max_countp,
 		 char **pattern_bufp, ULONGEST *pattern_lenp,
 		 CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
 		 bfd_boolean big_p)
@@ -137,7 +137,7 @@ parse_find_args (char *args, ULONGEST *max_countp,
       if (len < 0)
 	error (_("Invalid length."));
       /* Watch for overflows.  */
-      if (len > CORE_ADDR_MAX
+      if (len > addr_minus_one (gdbarch)
 	  || (start_addr + len - 1) < start_addr)
 	error (_("Search space too large."));
       search_space_len = len;
@@ -254,7 +254,7 @@ find_command (char *args, int from_tty)
   CORE_ADDR last_found_addr;
   struct cleanup *old_cleanups;
 
-  parse_find_args (args, &max_count, &pattern_buf, &pattern_len, 
+  parse_find_args (gdbarch, args, &max_count, &pattern_buf, &pattern_len,
 		   &start_addr, &search_space_len, big_p);
 
   old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1822,7 +1822,12 @@ get_frame_address_in_block (struct frame_info *this_frame)
   if (get_frame_type (next_frame) == NORMAL_FRAME
       && (get_frame_type (this_frame) == NORMAL_FRAME
 	  || get_frame_type (this_frame) == INLINE_FRAME))
-    return pc - 1;
+    {
+      /* Return PC - 1.  */
+      addr_offset_t offset = { 1 };
+
+      return addr_sub_offset (get_frame_arch (this_frame), pc, offset);
+    }
 
   return pc;
 }
--- a/gdb/hppa-hpux-tdep.c
+++ b/gdb/hppa-hpux-tdep.c
@@ -94,8 +94,12 @@ hppa32_hpux_in_solib_call_trampoline (struct gdbarch *gdbarch,
   struct unwind_table_entry *u;
 
   /* First see if PC is in one of the two C-library trampolines.  */
-  if (pc == hppa_symbol_address("$$dyncall") 
-      || pc == hppa_symbol_address("_sr4export"))
+
+  minsym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+  if (minsym != NULL && pc == SYMBOL_VALUE_ADDRESS (minsym))
+    return 1;
+  minsym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+  if (minsym != NULL && pc == SYMBOL_VALUE_ADDRESS (minsym))
     return 1;
 
   minsym = lookup_minimal_symbol_by_pc (pc);
@@ -317,7 +321,8 @@ hppa_hpux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 
   /* Addresses passed to dyncall may *NOT* be the actual address
      of the function.  So we may have to do something special.  */
-  if (pc == hppa_symbol_address("$$dyncall"))
+  msym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+  if (msym != NULL && pc == SYMBOL_VALUE_ADDRESS (msym))
     {
       pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
 
@@ -327,13 +332,18 @@ hppa_hpux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
       if (pc & 0x2)
 	pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size, byte_order);
     }
-  if (pc == hppa_symbol_address("$$dyncall_external"))
+  msym = lookup_minimal_symbol ("$$dyncall_external", NULL, NULL);
+  if (msym != NULL && pc == SYMBOL_VALUE_ADDRESS (msym))
     {
       pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
       pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size, byte_order);
     }
-  else if (pc == hppa_symbol_address("_sr4export"))
-    pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
+  else
+    {
+      msym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+      if (msym != NULL && pc == SYMBOL_VALUE_ADDRESS (msym))
+	pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22);
+    }
 
   /* Get the unwind descriptor corresponding to PC, return zero
      if no unwind was found.  */
@@ -853,6 +863,7 @@ hppa32_hpux_search_dummy_call_sequence (struct gdbarch *gdbarch, CORE_ADDR pc,
   CORE_ADDR addr, rp;
   char buf[4];
   unsigned int insn;
+  struct minimal_symbol *minsym;
 
   sec = find_pc_section (pc);
   obj = sec->objfile;
@@ -910,8 +921,10 @@ hppa32_hpux_search_dummy_call_sequence (struct gdbarch *gdbarch, CORE_ADDR pc,
 
   /* Finally, if this is the main executable, try to locate a sequence 
      from noshlibs */
-  addr = hppa_symbol_address ("noshlibs");
-  sec = find_pc_section (addr);
+  minsym = lookup_minimal_symbol ("noshlibs", NULL, NULL);
+  if (minsym == NULL)
+    return 0;
+  sec = find_pc_section (SYMBOL_VALUE_ADDRESS (minsym));
 
   if (sec && sec->objfile == obj)
     {
@@ -1473,11 +1486,17 @@ hppa_hpux_unwind_adjust_stub (struct frame_info *this_frame, CORE_ADDR base,
       stubpc = read_memory_integer (base - 24, word_size, byte_order);
       trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
     }
-  else if (hppa_symbol_address ("__gcc_plt_call") 
-           == get_pc_function_start (pcoq_head))
+  else
     {
-      stubpc = read_memory_integer (base - 8, word_size, byte_order);
-      trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
+      struct minimal_symbol *minsym;
+
+      minsym = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
+      if (minsym != NULL
+          && SYMBOL_VALUE_ADDRESS (minsym) == get_pc_function_start (pcoq_head))
+	{
+	  stubpc = read_memory_integer (base - 8, word_size, byte_order);
+	  trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
+	}
     }
 }
 
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -161,18 +161,6 @@ hppa_extract_17 (unsigned word)
 		      (word & 0x1) << 16, 17) << 2;
 }
 
-CORE_ADDR 
-hppa_symbol_address(const char *sym)
-{
-  struct minimal_symbol *minsym;
-
-  minsym = lookup_minimal_symbol (sym, NULL, NULL);
-  if (minsym)
-    return SYMBOL_VALUE_ADDRESS (minsym);
-  else
-    return (CORE_ADDR)-1;
-}
-
 struct hppa_objfile_private *
 hppa_init_objfile_priv_data (struct objfile *objfile)
 {
@@ -223,7 +211,7 @@ record_text_segment_lowaddr (bfd *abfd, asection *section, void *data)
 static void
 internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
 		     asection *section, unsigned int entries, unsigned int size,
-		     CORE_ADDR text_offset)
+		     addr_offset_t text_offset)
 {
   /* We will read the unwind entries into temporary memory, then
      fill in the actual unwind table.  */
@@ -242,7 +230,7 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
 	 Note that when loading a shared library (text_offset != 0) the
 	 unwinds are already relative to the text_offset that will be
 	 passed in.  */
-      if (gdbarch_tdep (gdbarch)->is_elf && text_offset == 0)
+      if (gdbarch_tdep (gdbarch)->is_elf && text_offset.a == 0)
 	{
           low_text_segment_address = -1;
 
@@ -250,11 +238,11 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
 				 record_text_segment_lowaddr, 
 				 &low_text_segment_address);
 
-	  text_offset = low_text_segment_address;
+	  text_offset.a = low_text_segment_address;
 	}
       else if (gdbarch_tdep (gdbarch)->solib_get_text_base)
         {
-	  text_offset = gdbarch_tdep (gdbarch)->solib_get_text_base (objfile);
+	  text_offset.a = gdbarch_tdep (gdbarch)->solib_get_text_base (objfile);
 	}
 
       bfd_get_section_contents (objfile->obfd, section, buf, 0, size);
@@ -265,10 +253,14 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
 	{
 	  table[i].region_start = bfd_get_32 (objfile->obfd,
 					      (bfd_byte *) buf);
-	  table[i].region_start += text_offset;
+	  table[i].region_start = addr_add_offset (get_objfile_arch (objfile),
+						   table[i].region_start,
+						   text_offset);
 	  buf += 4;
 	  table[i].region_end = bfd_get_32 (objfile->obfd, (bfd_byte *) buf);
-	  table[i].region_end += text_offset;
+	  table[i].region_end = addr_add_offset (get_objfile_arch (objfile),
+						 table[i].region_end,
+						 text_offset);
 	  buf += 4;
 	  tmp = bfd_get_32 (objfile->obfd, (bfd_byte *) buf);
 	  buf += 4;
@@ -325,7 +317,7 @@ read_unwind_info (struct objfile *objfile)
   unsigned unwind_size, stub_unwind_size, total_size;
   unsigned index, unwind_entries;
   unsigned stub_entries, total_entries;
-  CORE_ADDR text_offset;
+  addr_offset_t text_offset;
   struct hppa_unwind_info *ui;
   struct hppa_objfile_private *obj_private;
 
@@ -422,7 +414,9 @@ read_unwind_info (struct objfile *objfile)
 	     Stuff away the stub type into "reserved" fields.  */
 	  ui->table[index].region_start = bfd_get_32 (objfile->obfd,
 						      (bfd_byte *) buf);
-	  ui->table[index].region_start += text_offset;
+	  ui->table[index].region_start
+	    = addr_add_offset (get_objfile_arch (objfile),
+			       ui->table[index].region_start, text_offset);
 	  buf += 4;
 	  ui->table[index].stub_unwind.stub_type = bfd_get_8 (objfile->obfd,
 							  (bfd_byte *) buf);
@@ -2841,8 +2835,13 @@ static int
 hppa_in_dyncall (CORE_ADDR pc)
 {
   struct unwind_table_entry *u;
+  struct minimal_symbol *minsym;
+
+  minsym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+  if (minsym == NULL)
+    return 0;
 
-  u = find_unwind_entry (hppa_symbol_address ("$$dyncall"));
+  u = find_unwind_entry (SYMBOL_VALUE_ADDRESS (minsym));
   if (!u)
     return 0;
 
--- a/gdb/hppa-tdep.h
+++ b/gdb/hppa-tdep.h
@@ -223,7 +223,6 @@ unsigned hppa_extract_5r_store (unsigned int);
 int hppa_extract_17 (unsigned int);
 int hppa_extract_21 (unsigned);
 int hppa_extract_14 (unsigned);
-CORE_ADDR hppa_symbol_address(const char *sym);
 
 extern struct value *
   hppa_frame_prev_register_helper (struct frame_info *this_frame,
--- a/gdb/hppabsd-tdep.c
+++ b/gdb/hppabsd-tdep.c
@@ -87,8 +87,9 @@ hppabsd_find_global_pointer (struct gdbarch *gdbarch, struct value *function)
 		     we have to do it ourselves.  */
 		  pltgot = extract_unsigned_integer (buf, sizeof buf,
 						     byte_order);
-		  pltgot += ANOFFSET (sec->objfile->section_offsets,
-				      SECT_OFF_TEXT (sec->objfile));
+		  pltgot = addr_add_offset (gdbarch, pltgot,
+				       ANOFFSET (sec->objfile->section_offsets,
+						 SECT_OFF_TEXT (sec->objfile)));
 
 		  return pltgot;
 		}
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -793,7 +793,6 @@ i386_linux_resume (struct target_ops *ops,
     {
       struct regcache *regcache = get_thread_regcache (pid_to_ptid (pid));
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
       ULONGEST pc;
       gdb_byte buf[LINUX_SYSCALL_LEN];
 
@@ -821,12 +820,14 @@ i386_linux_resume (struct target_ops *ops,
 	  /* Then check the system call number.  */
 	  if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn)
 	    {
-	      ULONGEST sp, addr;
+	      ULONGEST sp;
+	      CORE_ADDR addr;
 	      unsigned long int eflags;
+	      struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
 
 	      regcache_cooked_read_unsigned (regcache, I386_ESP_REGNUM, &sp);
 	      if (syscall == SYS_rt_sigreturn)
-		addr = read_memory_integer (sp + 8, 4, byte_order) + 20;
+		addr = read_memory_typed_address (sp + 8, ptr_type) + 20;
 	      else
 		addr = sp;
 
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -654,7 +654,7 @@ inf_ptrace_fetch_register (struct regcache *regcache, int regnum)
 
   /* This isn't really an address, but ptrace thinks of it as one.  */
   addr = inf_ptrace_register_u_offset (gdbarch, regnum, 0);
-  if (addr == (CORE_ADDR)-1
+  if (addr == addr_minus_one (gdbarch)
       || gdbarch_cannot_fetch_register (gdbarch, regnum))
     {
       regcache_raw_supply (regcache, regnum, NULL);
@@ -715,7 +715,7 @@ inf_ptrace_store_register (const struct regcache *regcache, int regnum)
 
   /* This isn't really an address, but ptrace thinks of it as one.  */
   addr = inf_ptrace_register_u_offset (gdbarch, regnum, 1);
-  if (addr == (CORE_ADDR)-1 
+  if (addr == addr_minus_one (gdbarch)
       || gdbarch_cannot_store_register (gdbarch, regnum))
     return;
 
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -580,7 +580,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
   post_create_inferior (&current_target, 0);
 
   /* Start the target running.  */
-  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+  proceed (addr_minus_one (target_gdbarch), TARGET_SIGNAL_0, 0);
 
   /* Since there was no error, there's no need to finish the thread
      states here.  */
@@ -619,6 +619,8 @@ start_command (char *args, int from_tty)
 static int
 proceed_thread_callback (struct thread_info *thread, void *arg)
 {
+  struct gdbarch *gdbarch = target_thread_architecture (thread->ptid);
+
   /* We go through all threads individually instead of compressing
      into a single target `resume_all' request, because some threads
      may be stopped in internal breakpoints/events, or stopped waiting
@@ -633,7 +635,7 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
 
   switch_to_thread (thread->ptid);
   clear_proceed_status ();
-  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+  proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
   return 0;
 }
 
@@ -667,10 +669,13 @@ continue_1 (int all_threads)
     }
   else
     {
+      struct gdbarch *gdbarch;
+
       ensure_valid_thread ();
       ensure_not_running ();
       clear_proceed_status ();
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+      gdbarch = target_thread_architecture (inferior_ptid);
+      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
     }
 }
 
@@ -953,6 +958,8 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
 	 INFERIOR_PTID thread instead, which is the same thread when
 	 THREAD is set.  */
       struct thread_info *tp = inferior_thread ();
+      struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
+
       clear_proceed_status ();
       set_step_frame ();
 
@@ -1009,7 +1016,7 @@ which has no line number information.\n"), name);
 	tp->step_over_calls = STEP_OVER_ALL;
 
       tp->step_multi = (count > 1);
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 1);
 
       /* For async targets, register a continuation to do any
 	 additional steps.  For sync targets, the caller will handle
@@ -1143,11 +1150,13 @@ signal_command (char *signum_exp, int from_tty)
 {
   enum target_signal oursig;
   int async_exec = 0;
+  struct gdbarch *gdbarch;
 
   dont_repeat ();		/* Too dangerous.  */
   ERROR_NO_INFERIOR;
   ensure_valid_thread ();
   ensure_not_running ();
+  gdbarch = target_thread_architecture (inferior_ptid);
 
   /* Find out whether we must run in the background.  */
   if (signum_exp != NULL)
@@ -1195,7 +1204,7 @@ signal_command (char *signum_exp, int from_tty)
     }
 
   clear_proceed_status ();
-  proceed ((CORE_ADDR) -1, oursig, 0);
+  proceed (addr_minus_one (gdbarch), oursig, 0);
 }
 
 /* Proceed until we reach a different source line with pc greater than
@@ -1214,6 +1223,7 @@ until_next_command (int from_tty)
   struct symbol *func;
   struct symtab_and_line sal;
   struct thread_info *tp = inferior_thread ();
+  struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
   clear_proceed_status ();
   set_step_frame ();
@@ -1249,7 +1259,7 @@ until_next_command (int from_tty)
 
   tp->step_multi = 0;		/* Only one call to proceed */
 
-  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+  proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 1);
 }
 
 static void
@@ -1480,7 +1490,7 @@ finish_backward (struct symbol *function)
          until we've done another reverse single-step.  */
       make_breakpoint_silent (breakpoint);
       old_chain = make_cleanup_delete_breakpoint (breakpoint);
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
       /* We will be stopped when proceed returns.  */
       back_up = bpstat_find_breakpoint (tp->stop_bpstat, breakpoint) != NULL;
       do_cleanups (old_chain);
@@ -1489,11 +1499,14 @@ finish_backward (struct symbol *function)
     back_up = 1;
   if (back_up)
     {
+      struct frame_info *frame = get_selected_frame (NULL);
+      struct gdbarch *gdbarch = get_frame_arch (frame);
+
       /* If in fact we hit the step-resume breakpoint (and not
 	 some other breakpoint), then we're almost there --
 	 we just need to back up by one more single-step.  */
       tp->step_range_start = tp->step_range_end = 1;
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 1);
     }
   return;
 }
@@ -1526,7 +1539,7 @@ finish_forward (struct symbol *function, struct frame_info *frame)
   cargs->function = function;
   add_continuation (tp, finish_command_continuation, cargs,
                     finish_command_continuation_free_arg);
-  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+  proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
 
   discard_cleanups (old_chain);
   if (!target_can_async_p ())
@@ -1588,6 +1601,7 @@ finish_command (char *arg, int from_tty)
 	 step_range_end, because then infrun will think this is nexti,
 	 and not step over the rest of this inlined function call.  */
       struct thread_info *tp = inferior_thread ();
+      struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
       struct symtab_and_line empty_sal;
       init_sal (&empty_sal);
       set_step_info (frame, empty_sal);
@@ -1602,7 +1616,7 @@ finish_command (char *arg, int from_tty)
 	  print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
 	}
 
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 1);
       return;
     }
 
@@ -2162,9 +2176,11 @@ proceed_after_attach_callback (struct thread_info *thread,
       && !thread->stop_requested
       && thread->stop_signal == TARGET_SIGNAL_0)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (thread->ptid);
+
       switch_to_thread (thread->ptid);
       clear_proceed_status ();
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
     }
 
   return 0;
@@ -2264,8 +2280,11 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
 	{
 	  if (inferior_thread ()->stop_signal == TARGET_SIGNAL_0)
 	    {
+	      struct gdbarch *gdbarch;
+
+	      gdbarch = target_thread_architecture (inferior_ptid);
 	      clear_proceed_status ();
-	      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+	      proceed (addr_minus_one (gdbarch), TARGET_SIGNAL_DEFAULT, 0);
 	    }
 	}
     }
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -484,7 +484,8 @@ proceed_after_vfork_done (struct thread_info *thread,
 
       switch_to_thread (thread->ptid);
       clear_proceed_status ();
-      proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+      proceed (addr_minus_one (target_thread_architecture (thread->ptid)),
+	       TARGET_SIGNAL_DEFAULT, 0);
     }
 
   return 0;
@@ -1730,7 +1731,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   if (step < 0)
     stop_after_trap = 1;
 
-  if (addr == (CORE_ADDR) -1)
+  if (addr == addr_minus_one (gdbarch))
     {
       if (pc == stop_pc && breakpoint_here_p (aspace, pc)
 	  && execution_direction != EXEC_REVERSE)
--- a/gdb/iq2000-tdep.c
+++ b/gdb/iq2000-tdep.c
@@ -55,9 +55,6 @@ enum gdb_regnum
   E_NUM_REGS         = E_PC_REGNUM + 1
 };
 
-/* Use an invalid address value as 'not available' marker.  */
-enum { REG_UNAVAIL = (CORE_ADDR) -1 };
-
 struct iq2000_frame_cache
 {
   /* Base address.  */
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -88,7 +88,8 @@ java_value_print (struct value *val, struct ui_file *stream,
       if (el_type == NULL)
 	{
 	  CORE_ADDR element;
-	  CORE_ADDR next_element = -1; /* dummy initial value */
+	  /* dummy initial value */
+	  CORE_ADDR next_element = addr_minus_one (gdbarch);
 
 	  /* Skip object header and length. */
 	  address += get_java_object_header_size (gdbarch) + 4;
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -5092,12 +5092,7 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object,
      Compare ADDR_BIT first to avoid a compiler warning on shift overflow.  */
 
   if (object == TARGET_OBJECT_MEMORY)
-    {
-      int addr_bit = gdbarch_addr_bit (target_gdbarch);
-
-      if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
-	offset &= ((ULONGEST) 1 << addr_bit) - 1;
-    }
+    addr_width_assert (target_gdbarch, offset);
 
   xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
 				  offset, len);
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -758,7 +758,8 @@ m68hc11_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 	return sal.end;
     }
 
-  pc = m68hc11_scan_prologue (gdbarch, pc, (CORE_ADDR) -1, &tmp_cache);
+  pc = m68hc11_scan_prologue (gdbarch, pc, addr_minus_one (gdbarch),
+			      &tmp_cache);
   return pc;
 }
 
@@ -816,7 +817,7 @@ m68hc11_frame_unwind_cache (struct frame_info *this_frame,
 
   info->saved_regs[HARD_PC_REGNUM].addr = info->size;
 
-  if (info->sp_offset != (CORE_ADDR) -1)
+  if (info->sp_offset != addr_minus_one (gdbarch))
     {
       info->saved_regs[HARD_PC_REGNUM].addr = info->sp_offset;
       this_base = get_frame_register_unsigned (this_frame, HARD_SP_REGNUM);
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -848,7 +848,8 @@ m68k_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   int op;
 
   cache.locals = -1;
-  pc = m68k_analyze_prologue (gdbarch, start_pc, (CORE_ADDR) -1, &cache);
+  pc = m68k_analyze_prologue (gdbarch, start_pc, addr_minus_one (gdbarch),
+			      &cache);
   if (cache.locals < 0)
     return start_pc;
   return pc;
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -571,18 +571,24 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
          The value of a stBlock symbol is the displacement from the
          procedure address.  */
       if (sh->st != stEnd && sh->st != stBlock)
-	sh->value += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+	sh->value = addr_add_offset (gdbarch, sh->value,
+				     ANOFFSET (section_offsets,
+					       SECT_OFF_TEXT (objfile)));
       break;
     case scData:
     case scSData:
     case scRData:
     case scPData:
     case scXData:
-      sh->value += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
+      sh->value = addr_add_offset (gdbarch, sh->value,
+				   ANOFFSET (section_offsets,
+					     SECT_OFF_DATA (objfile)));
       break;
     case scBss:
     case scSBss:
-      sh->value += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
+      sh->value = addr_add_offset (gdbarch, sh->value,
+				   ANOFFSET (section_offsets,
+					     SECT_OFF_BSS (objfile)));
       break;
     }
 
@@ -2516,12 +2522,16 @@ parse_partial_symbols (struct objfile *objfile)
 	{
 	case stProc:
 	  /* Beginnning of Procedure */
-	  svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	  svalue = addr_add_offset (gdbarch, svalue,
+				    ANOFFSET (objfile->section_offsets,
+					      SECT_OFF_TEXT (objfile)));
 	  break;
 	case stStaticProc:
 	  /* Load time only static procs */
 	  ms_type = mst_file_text;
-	  svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	  svalue = addr_add_offset (gdbarch, svalue,
+				    ANOFFSET (objfile->section_offsets,
+					      SECT_OFF_TEXT (objfile)));
 	  break;
 	case stGlobal:
 	  /* External symbol */
@@ -2534,18 +2544,24 @@ parse_partial_symbols (struct objfile *objfile)
 	  else if (SC_IS_DATA (ext_in->asym.sc))
 	    {
 	      ms_type = mst_data;
-	      svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  SECT_OFF_DATA (objfile)));
 	    }
 	  else if (SC_IS_BSS (ext_in->asym.sc))
 	    {
 	      ms_type = mst_bss;
-	      svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  SECT_OFF_BSS (objfile)));
 	    }
           else if (SC_IS_SBSS (ext_in->asym.sc))
             {
               ms_type = mst_bss;
-              svalue += ANOFFSET (objfile->section_offsets, 
-                                  get_section_index (objfile, ".sbss"));
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  get_section_index (objfile,
+								     ".sbss")));
             }
 	  else
 	    ms_type = mst_abs;
@@ -2579,7 +2595,9 @@ parse_partial_symbols (struct objfile *objfile)
                 continue;
                 
 	      ms_type = mst_file_text;
-	      svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  SECT_OFF_TEXT (objfile)));
 	    }
 	  else if (SC_IS_DATA (ext_in->asym.sc))
 	    {
@@ -2587,7 +2605,9 @@ parse_partial_symbols (struct objfile *objfile)
                 continue;
 
 	      ms_type = mst_file_data;
-	      svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  SECT_OFF_DATA (objfile)));
 	    }
 	  else if (SC_IS_BSS (ext_in->asym.sc))
 	    {
@@ -2595,7 +2615,9 @@ parse_partial_symbols (struct objfile *objfile)
                 continue;
 
 	      ms_type = mst_file_bss;
-	      svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  SECT_OFF_BSS (objfile)));
 	    }
           else if (SC_IS_SBSS (ext_in->asym.sc))
             {
@@ -2605,7 +2627,9 @@ parse_partial_symbols (struct objfile *objfile)
                 continue;
 
               ms_type = mst_file_bss;
-              svalue += ANOFFSET (objfile->section_offsets, sbss_sect_index);
+	      svalue = addr_add_offset (gdbarch, svalue,
+					ANOFFSET (objfile->section_offsets,
+						  sbss_sect_index));
             }
 	  else
 	    ms_type = mst_abs;
@@ -2650,7 +2674,9 @@ parse_partial_symbols (struct objfile *objfile)
 	{
 	  textlow = fh->adr;
 	  if (relocatable || textlow != 0)
-	    textlow += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+	    textlow = addr_add_offset (gdbarch, textlow,
+				       ANOFFSET (objfile->section_offsets,
+						 SECT_OFF_TEXT (objfile)));
 	}
       else
 	textlow = 0;
@@ -2739,7 +2765,9 @@ parse_partial_symbols (struct objfile *objfile)
 		      CORE_ADDR procaddr;
 		      long isym;
 
-		      sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		      sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		      if (sh.st == stStaticProc)
 			{
 			  namestring = debug_info->ss + fh->issBase + sh.iss;
@@ -2786,7 +2814,9 @@ parse_partial_symbols (struct objfile *objfile)
 			case scPData:
 			case scXData:
 			  namestring = debug_info->ss + fh->issBase + sh.iss;
-			  sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+			  sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
                           record_minimal_symbol (namestring, sh.value,
                                                  mst_file_data, sh.sc,
                                                  objfile);
@@ -2796,7 +2826,9 @@ parse_partial_symbols (struct objfile *objfile)
 			  /* FIXME!  Shouldn't this use cases for bss, 
 			     then have the default be abs? */
 			  namestring = debug_info->ss + fh->issBase + sh.iss;
-			  sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
+			  sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_BSS (objfile)));
                           record_minimal_symbol (namestring, sh.value,
                                                  mst_file_bss, sh.sc,
                                                  objfile);
@@ -2851,19 +2883,25 @@ parse_partial_symbols (struct objfile *objfile)
 
 		  case N_TEXT | N_EXT:
 		  case N_NBTEXT | N_EXT:
-		    sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		    sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		    goto record_it;
 
 		  case N_DATA | N_EXT:
 		  case N_NBDATA | N_EXT:
-		    sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+		    sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 		    goto record_it;
 
 		  case N_BSS:
 		  case N_BSS | N_EXT:
 		  case N_NBBSS | N_EXT:
 		  case N_SETV | N_EXT:		/* FIXME, is this in BSS? */
-		    sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
+		    sh.value = addr_add_offset (gdbarch, sh.value,
+					     ANOFFSET (objfile->section_offsets,
+						       SECT_OFF_BSS (objfile)));
 		    goto record_it;
 
 		  case N_ABS | N_EXT:
@@ -2885,7 +2923,9 @@ parse_partial_symbols (struct objfile *objfile)
 		    continue;
 
 		  case N_DATA:
-		    sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+		    sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 		    goto record_it;
 
 		  case N_UNDF | N_EXT:
@@ -2931,7 +2971,9 @@ parse_partial_symbols (struct objfile *objfile)
 		      char *p;
 		      int prev_textlow_not_set;
 
-		      valu = sh.value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		      valu = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 
 		      prev_textlow_not_set = textlow_not_set;
 
@@ -3087,7 +3129,9 @@ parse_partial_symbols (struct objfile *objfile)
 		    switch (p[1])
 		      {
 		      case 'S':
-			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+			sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 
 			if (gdbarch_static_transform_name_p (gdbarch))
 			  namestring = gdbarch_static_transform_name
@@ -3100,7 +3144,9 @@ parse_partial_symbols (struct objfile *objfile)
 					     psymtab_language, objfile);
 			continue;
 		      case 'G':
-			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+			sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 			/* The addresses in these entries are reported to be
 			   wrong.  See the code that reads 'G's for symtabs. */
 			add_psymbol_to_list (namestring, p - namestring, 1,
@@ -3237,7 +3283,9 @@ parse_partial_symbols (struct objfile *objfile)
 			    function_outside_compilation_unit_complaint (name);
 			    xfree (name);
 			  }
-			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+			sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_BLOCK,
 					     &objfile->static_psymbols,
@@ -3258,7 +3306,9 @@ parse_partial_symbols (struct objfile *objfile)
 			    function_outside_compilation_unit_complaint (name);
 			    xfree (name);
 			  }
-			sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+			sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 			add_psymbol_to_list (namestring, p - namestring, 1,
 					     VAR_DOMAIN, LOC_BLOCK,
 					     &objfile->global_psymbols,
@@ -3413,18 +3463,24 @@ parse_partial_symbols (struct objfile *objfile)
 		  /* The value of a stEnd symbol is the displacement from the
 		     corresponding start symbol value, do not relocate it.  */
 		  if (sh.st != stEnd)
-		    sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		    sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		  break;
 		case scData:
 		case scSData:
 		case scRData:
 		case scPData:
 		case scXData:
-		  sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+		  sh.value = addr_add_offset (gdbarch, sh.value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 		  break;
 		case scBss:
 		case scSBss:
-		  sh.value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
+		  sh.value = addr_add_offset (gdbarch, sh.value,
+					     ANOFFSET (objfile->section_offsets,
+						       SECT_OFF_BSS (objfile)));
 		  break;
 		}
 
@@ -3636,18 +3692,24 @@ parse_partial_symbols (struct objfile *objfile)
 		{
 		case scText:
 		case scRConst:
-		  svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		  svalue = addr_add_offset (gdbarch, svalue,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		  break;
 		case scData:
 		case scSData:
 		case scRData:
 		case scPData:
 		case scXData:
-		  svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+		  svalue = addr_add_offset (gdbarch, svalue,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 		  break;
 		case scBss:
 		case scSBss:
-		  svalue += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
+		  svalue = addr_add_offset (gdbarch, svalue,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_BSS (objfile)));
 		  break;
 		}
 
@@ -4005,8 +4067,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename)
 		      && previous_stab_code != (unsigned char) N_SO
 		      && *name == '\000')
 		    {
-		      valu += ANOFFSET (pst->section_offsets,
-					SECT_OFF_TEXT (pst->objfile));
+		      valu = addr_add_offset (gdbarch, valu,
+				       ANOFFSET (pst->section_offsets,
+						 SECT_OFF_TEXT (pst->objfile)));
 		      previous_stab_code = N_SO;
 		      st = end_symtab (valu, pst->objfile,
 				       SECT_OFF_TEXT (pst->objfile));
@@ -4056,7 +4119,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, char *filename)
 	      else
 		{
 		  /* Handle encoded stab line number. */
-		  valu += ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (pst->objfile));
+		  valu = addr_add_offset (gdbarch, valu,
+				       ANOFFSET (pst->section_offsets,
+						 SECT_OFF_TEXT (pst->objfile)));
 		  record_line (current_subfile, sh.index,
 			       gdbarch_addr_bits_remove (gdbarch, valu));
 		}
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -191,7 +191,8 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
 
   switch_to_thread (thread->ptid);
   clear_proceed_status ();
-  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+  proceed (addr_minus_one (target_thread_architecture (thread->ptid)),
+	   TARGET_SIGNAL_DEFAULT, 0);
   return 0;
 }
 
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -84,9 +84,9 @@ mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
   else if (regno == mips_regnum (gdbarch)->pc)
     regaddr = PC;
   else if (regno == mips_regnum (gdbarch)->cause)
-    regaddr = store? (CORE_ADDR) -1 : CAUSE;
+    regaddr = store ? addr_minus_one (gdbarch) : CAUSE;
   else if (regno == mips_regnum (gdbarch)->badvaddr)
-    regaddr = store? (CORE_ADDR) -1 : BADVADDR;
+    regaddr = store ? addr_minus_one (gdbarch) : BADVADDR;
   else if (regno == mips_regnum (gdbarch)->lo)
     regaddr = MMLO;
   else if (regno == mips_regnum (gdbarch)->hi)
@@ -94,11 +94,11 @@ mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
   else if (regno == mips_regnum (gdbarch)->fp_control_status)
     regaddr = FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
-    regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+    regaddr = store ? addr_minus_one (gdbarch) : FPC_EIR;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
-    regaddr = (CORE_ADDR) -1;
+    regaddr = addr_minus_one (gdbarch);
 
   return regaddr;
 }
@@ -119,9 +119,9 @@ mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
   else if (regno == mips_regnum (gdbarch)->pc)
     regaddr = MIPS64_PC;
   else if (regno == mips_regnum (gdbarch)->cause)
-    regaddr = store? (CORE_ADDR) -1 : MIPS64_CAUSE;
+    regaddr = store ? addr_minus_one (gdbarch) : MIPS64_CAUSE;
   else if (regno == mips_regnum (gdbarch)->badvaddr)
-    regaddr = store? (CORE_ADDR) -1 : MIPS64_BADVADDR;
+    regaddr = store ? addr_minus_one (gdbarch) : MIPS64_BADVADDR;
   else if (regno == mips_regnum (gdbarch)->lo)
     regaddr = MIPS64_MMLO;
   else if (regno == mips_regnum (gdbarch)->hi)
@@ -129,11 +129,11 @@ mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
   else if (regno == mips_regnum (gdbarch)->fp_control_status)
     regaddr = MIPS64_FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
-    regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+    regaddr = store ? addr_minus_one (gdbarch) : MIPS64_FPC_EIR;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
-    regaddr = (CORE_ADDR) -1;
+    regaddr = addr_minus_one (gdbarch);
 
   return regaddr;
 }
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -2392,7 +2392,7 @@ static int
 deal_with_atomic_sequence (struct gdbarch *gdbarch,
 			   struct address_space *aspace, CORE_ADDR pc)
 {
-  CORE_ADDR breaks[2] = {-1, -1};
+  CORE_ADDR breaks[2] = { addr_minus_one (gdbarch), addr_minus_one (gdbarch) };
   CORE_ADDR loc = pc;
   CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination.  */
   unsigned long insn;
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -180,6 +180,7 @@ static void
 read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
 			       struct objfile *objfile)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = objfile->obfd;
   struct alphacoff_dynsecinfo si;
   char *sym_secptr;
@@ -352,7 +353,9 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
 		ms_type = mst_text;
 	      else
 		ms_type = mst_file_text;
-	      sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
+	      sym_value = addr_add_offset (gdbarch, sym_value,
+	                                   ANOFFSET (section_offsets,
+					             SECT_OFF_TEXT (objfile)));
 	    }
 	  else if (sym_shndx == SHN_MIPS_DATA)
 	    {
@@ -360,7 +363,9 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
 		ms_type = mst_data;
 	      else
 		ms_type = mst_file_data;
-	      sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
+	      sym_value = addr_add_offset (gdbarch, sym_value,
+					   ANOFFSET (section_offsets,
+						     SECT_OFF_DATA (objfile)));
 	    }
 	  else if (sym_shndx == SHN_MIPS_ACOMMON)
 	    {
@@ -368,7 +373,9 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
 		ms_type = mst_bss;
 	      else
 		ms_type = mst_file_bss;
-	      sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
+	      sym_value = addr_add_offset (gdbarch, sym_value,
+					   ANOFFSET (section_offsets,
+						     SECT_OFF_BSS (objfile)));
 	    }
 	  else if (sym_shndx == SHN_ABS)
 	    {
--- a/gdb/moxie-tdep.c
+++ b/gdb/moxie-tdep.c
@@ -47,7 +47,7 @@
 extern void _initialize_moxie_tdep (void);
 
 /* Use an invalid address value as 'not available' marker.  */
-enum { REG_UNAVAIL = (CORE_ADDR) -1 };
+#define REG_UNAVAIL(gdbarch) addr_minus_one (gdbarch)
 
 struct moxie_frame_cache
 {
@@ -360,7 +360,7 @@ moxie_return_value (struct gdbarch *gdbarch, struct type *func_type,
 /* Allocate and initialize a moxie_frame_cache object.  */
 
 static struct moxie_frame_cache *
-moxie_alloc_frame_cache (void)
+moxie_alloc_frame_cache (struct gdbarch *gdbarch)
 {
   struct moxie_frame_cache *cache;
   int i;
@@ -372,7 +372,7 @@ moxie_alloc_frame_cache (void)
   cache->pc = 0;
   cache->framesize = 0;
   for (i = 0; i < MOXIE_NUM_REGS; ++i)
-    cache->saved_regs[i] = REG_UNAVAIL;
+    cache->saved_regs[i] = REG_UNAVAIL (gdbarch);
 
   return cache;
 }
@@ -382,6 +382,7 @@ moxie_alloc_frame_cache (void)
 static struct moxie_frame_cache *
 moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct moxie_frame_cache *cache;
   CORE_ADDR current_pc;
   int i;
@@ -389,7 +390,7 @@ moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
   if (*this_cache)
     return *this_cache;
 
-  cache = moxie_alloc_frame_cache ();
+  cache = moxie_alloc_frame_cache (gdbarch);
   *this_cache = cache;
 
   cache->base = get_frame_register_unsigned (this_frame, MOXIE_FP_REGNUM);
@@ -399,15 +400,12 @@ moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
   cache->pc = get_frame_func (this_frame);
   current_pc = get_frame_pc (this_frame);
   if (cache->pc)
-    {
-      struct gdbarch *gdbarch = get_frame_arch (this_frame);
-      moxie_analyze_prologue (cache->pc, current_pc, cache, gdbarch);
-    }
+    moxie_analyze_prologue (cache->pc, current_pc, cache, gdbarch);
 
   cache->saved_sp = cache->base - cache->framesize;
 
   for (i = 0; i < MOXIE_NUM_REGS; ++i)
-    if (cache->saved_regs[i] != REG_UNAVAIL)
+    if (cache->saved_regs[i] != REG_UNAVAIL (gdbarch))
       cache->saved_regs[i] = cache->base - cache->saved_regs[i];
 
   return cache;
@@ -444,6 +442,7 @@ static struct value *
 moxie_frame_prev_register (struct frame_info *this_frame,
 			  void **this_prologue_cache, int regnum)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
 						   this_prologue_cache);
 
@@ -452,7 +451,8 @@ moxie_frame_prev_register (struct frame_info *this_frame,
   if (regnum == MOXIE_SP_REGNUM && cache->saved_sp)
     return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
 
-  if (regnum < MOXIE_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
+  if (regnum < MOXIE_NUM_REGS
+      && cache->saved_regs[regnum] != REG_UNAVAIL (gdbarch))
     return frame_unwind_got_memory (this_frame, regnum,
 				    cache->saved_regs[regnum]);
 
--- a/gdb/nto-tdep.c
+++ b/gdb/nto-tdep.c
@@ -265,7 +265,7 @@ struct lm_info
 static CORE_ADDR
 LM_ADDR (struct so_list *so)
 {
-  if (so->lm_info->l_addr == (CORE_ADDR)-1)
+  if (so->lm_info->l_addr == addr_minus_one (target_gdbarch))
     {
       struct link_map_offsets *lmo = nto_fetch_link_map_offsets ();
       struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -702,6 +702,7 @@ free_all_objfiles (void)
 static int
 objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct obj_section *s;
   struct section_offsets *delta =
     ((struct section_offsets *) 
@@ -712,9 +713,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
     int something_changed = 0;
     for (i = 0; i < objfile->num_sections; ++i)
       {
-	delta->offsets[i] =
-	  ANOFFSET (new_offsets, i) - ANOFFSET (objfile->section_offsets, i);
-	if (ANOFFSET (delta, i) != 0)
+	delta->offsets[i] = addr_offset_sub (gdbarch,
+					     ANOFFSET (new_offsets, i),
+					ANOFFSET (objfile->section_offsets, i));
+	if (ANOFFSET (delta, i).a != 0)
 	  something_changed = 1;
       }
     if (!something_changed)
@@ -736,7 +738,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
       if (l)
 	{
 	  for (i = 0; i < l->nitems; ++i)
-	    l->item[i].pc += ANOFFSET (delta, s->block_line_section);
+	    l->item[i].pc = addr_add_offset (gdbarch,
+					     l->item[i].pc,
+					     ANOFFSET (delta,
+						       s->block_line_section));
 	}
 
       /* Don't relocate a shared blockvector more than once.  */
@@ -755,8 +760,14 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
 	  struct dict_iterator iter;
 
 	  b = BLOCKVECTOR_BLOCK (bv, i);
-	  BLOCK_START (b) += ANOFFSET (delta, s->block_line_section);
-	  BLOCK_END (b) += ANOFFSET (delta, s->block_line_section);
+	  BLOCK_START (b) = addr_add_offset (gdbarch,
+					     BLOCK_START (b),
+					     ANOFFSET (delta,
+					               s->block_line_section));
+	  BLOCK_END (b) = addr_add_offset (gdbarch,
+					   BLOCK_END (b),
+					   ANOFFSET (delta,
+						     s->block_line_section));
 
 	  ALL_BLOCK_SYMBOLS (b, iter, sym)
 	    {
@@ -770,8 +781,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
 		   || SYMBOL_CLASS (sym) == LOC_STATIC)
 		  && SYMBOL_SECTION (sym) >= 0)
 		{
-		  SYMBOL_VALUE_ADDRESS (sym) +=
-		    ANOFFSET (delta, SYMBOL_SECTION (sym));
+		  SYMBOL_VALUE_ADDRESS (sym) = addr_add_offset (gdbarch,
+						     SYMBOL_VALUE_ADDRESS (sym),
+					       ANOFFSET (delta,
+							 SYMBOL_SECTION (sym)));
 		}
 	    }
 	}
@@ -787,8 +800,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
 
     ALL_OBJFILE_PSYMTABS (objfile, p)
     {
-      p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
-      p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+      p->textlow = addr_add_offset (gdbarch, p->textlow,
+				    ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
+      p->texthigh = addr_add_offset (gdbarch, p->texthigh,
+				     ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
     }
   }
 
@@ -801,8 +816,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
       {
 	fixup_psymbol_section (*psym, objfile);
 	if (SYMBOL_SECTION (*psym) >= 0)
-	  SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
-						    SYMBOL_SECTION (*psym));
+	  SYMBOL_VALUE_ADDRESS (*psym) = addr_add_offset (gdbarch,
+						   SYMBOL_VALUE_ADDRESS (*psym),
+					     ANOFFSET (delta,
+						       SYMBOL_SECTION (*psym)));
       }
     for (psym = objfile->static_psymbols.list;
 	 psym < objfile->static_psymbols.next;
@@ -810,8 +827,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
       {
 	fixup_psymbol_section (*psym, objfile);
 	if (SYMBOL_SECTION (*psym) >= 0)
-	  SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
-						    SYMBOL_SECTION (*psym));
+	  SYMBOL_VALUE_ADDRESS (*psym) = addr_add_offset (gdbarch,
+						   SYMBOL_VALUE_ADDRESS (*psym),
+					     ANOFFSET (delta,
+						       SYMBOL_SECTION (*psym)));
       }
   }
 
@@ -819,7 +838,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
     struct minimal_symbol *msym;
     ALL_OBJFILE_MSYMBOLS (objfile, msym)
       if (SYMBOL_SECTION (msym) >= 0)
-      SYMBOL_VALUE_ADDRESS (msym) += ANOFFSET (delta, SYMBOL_SECTION (msym));
+	SYMBOL_VALUE_ADDRESS (msym) = addr_add_offset (gdbarch,
+						    SYMBOL_VALUE_ADDRESS (msym),
+					      ANOFFSET (delta,
+							SYMBOL_SECTION (msym)));
   }
   /* Relocating different sections by different amounts may cause the symbols
      to be out of order.  */
@@ -832,9 +854,15 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
       struct obj_section *s;
       s = find_pc_section (objfile->ei.entry_point);
       if (s)
-        objfile->ei.entry_point += ANOFFSET (delta, s->the_bfd_section->index);
+        objfile->ei.entry_point = addr_add_offset (gdbarch,
+						   objfile->ei.entry_point,
+					  ANOFFSET (delta,
+						    s->the_bfd_section->index));
       else
-        objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
+        objfile->ei.entry_point = addr_add_offset (gdbarch,
+						   objfile->ei.entry_point,
+					    ANOFFSET (delta,
+						      SECT_OFF_TEXT (objfile)));
     }
 
   {
@@ -880,6 +908,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
        debug_objfile;
        debug_objfile = objfile_separate_debug_iterate (objfile, debug_objfile))
     {
+      struct gdbarch *gdbarch = get_objfile_arch (debug_objfile);
       struct section_addr_info *objfile_addrs;
       struct section_offsets *new_debug_offsets;
       int new_debug_num_sections;
@@ -891,14 +920,14 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
       /* Here OBJFILE_ADDRS contain the correct absolute addresses, the
 	 relative ones must be already created according to debug_objfile.  */
 
-      addr_info_make_relative (objfile_addrs, debug_objfile->obfd);
+      addr_info_make_relative (gdbarch, objfile_addrs, debug_objfile->obfd);
 
       gdb_assert (debug_objfile->num_sections
 		  == bfd_count_sections (debug_objfile->obfd));
       new_debug_offsets = xmalloc (SIZEOF_N_SECTION_OFFSETS
 						 (debug_objfile->num_sections));
       make_cleanup (xfree, new_debug_offsets);
-      relative_addr_info_to_section_offsets (new_debug_offsets,
+      relative_addr_info_to_section_offsets (gdbarch, new_debug_offsets,
 					     debug_objfile->num_sections,
 					     objfile_addrs);
 
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -126,16 +126,20 @@ struct obj_section
   (((s)->objfile->section_offsets)->offsets[(s)->the_bfd_section->index])
 
 /* The memory address of section S (vma + offset).  */
-#define obj_section_addr(s)				      		\
-  (bfd_get_section_vma ((s)->objfile->abfd, s->the_bfd_section)		\
-   + obj_section_offset (s))
+#define obj_section_addr(s)						\
+  addr_add_offset (get_objfile_arch ((s)->objfile),			\
+		   bfd_get_section_vma ((s)->objfile->abfd,		\
+		                        s->the_bfd_section),		\
+		   obj_section_offset (s))
 
 /* The one-passed-the-end memory address of section S
    (vma + size + offset).  */
 #define obj_section_endaddr(s)						\
-  (bfd_get_section_vma ((s)->objfile->abfd, s->the_bfd_section)		\
-   + bfd_get_section_size ((s)->the_bfd_section)			\
-   + obj_section_offset (s))
+  addr_add_offset (get_objfile_arch ((s)->objfile),			\
+		   (bfd_get_section_vma ((s)->objfile->abfd,		\
+					 s->the_bfd_section)		\
+		    + bfd_get_section_size ((s)->the_bfd_section)),	\
+		   obj_section_offset (s))
 
 /* The "objstats" structure provides a place for gdb to record some
    interesting information about its internal state at runtime, on a
--- a/gdb/prologue-value.c
+++ b/gdb/prologue-value.c
@@ -420,13 +420,20 @@ find_entry (struct pv_area *area, CORE_ADDR offset)
      discontinuity.  */
   while (((e->next->offset - offset) & area->addr_mask)
          < ((e->offset - offset) & area->addr_mask))
+    {
+      gdb_assert ((e->offset & ~area->addr_mask) == 0);
     e = e->next;
+    }
 
   /* If the previous entry would be better than the current one, then
      scan backwards.  */
   while (((e->prev->offset - offset) & area->addr_mask)
          < ((e->offset - offset) & area->addr_mask))
+    {
+      gdb_assert ((e->offset & ~area->addr_mask) == 0);
     e = e->prev;
+    }
+  gdb_assert ((e->offset & ~area->addr_mask) == 0);
 
   /* In case there's some locality to the searches, set the area's
      pointer to the entry we've found.  */
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2854,7 +2854,9 @@ get_offsets (void)
 
   if (do_segments)
     {
-      int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data,
+      int ret = symfile_map_offsets_to_segments (get_objfile_arch
+							      (symfile_objfile),
+						 symfile_objfile->obfd, data,
 						 offs, num_segments, segments);
 
       if (ret == 0 && !do_sections)
@@ -2869,14 +2871,18 @@ get_offsets (void)
 
   if (do_sections)
     {
-      offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+      struct gdbarch *gdbarch = get_objfile_arch (symfile_objfile);
+
+      offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = addr_to_offset (gdbarch,
+								     text_addr);
 
       /* This is a temporary kludge to force data and bss to use the same offsets
 	 because that's what nlmconv does now.  The real solution requires changes
 	 to the stub and remote.c that I don't have time to do right now.  */
 
-      offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
-      offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+      offs->offsets[SECT_OFF_DATA (symfile_objfile)]
+      = offs->offsets[SECT_OFF_BSS (symfile_objfile)] = addr_to_offset (gdbarch,
+								     data_addr);
     }
 
   objfile_relocate (symfile_objfile, offs);
@@ -5728,8 +5734,7 @@ remote_address_masked (CORE_ADDR addr)
       /* Only create a mask when that mask can safely be constructed
          in a ULONGEST variable.  */
       ULONGEST mask = 1;
-      mask = (mask << address_size) - 1;
-      addr &= mask;
+      gdb_assert ((addr & -(mask << address_size)) == 0);
     }
   return addr;
 }
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1087,7 +1087,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
   struct address_space *aspace = get_frame_address_space (frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR pc = get_frame_pc (frame);
-  CORE_ADDR breaks[2] = {-1, -1};
+  CORE_ADDR breaks[2] = { addr_minus_one (gdbarch), addr_minus_one (gdbarch) };
   CORE_ADDR loc = pc;
   CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence.  */
   int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
--- a/gdb/s390-nat.c
+++ b/gdb/s390-nat.c
@@ -293,12 +293,13 @@ s390_stopped_by_watchpoint (void)
 static void
 s390_fix_watch_points (ptid_t ptid)
 {
+  struct gdbarch *gdbarch = get_thread_arch_regcache (ptid);
   int tid;
 
   per_struct per_info;
   ptrace_area parea;
 
-  CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
+  CORE_ADDR watch_lo_addr = addr_minus_one (gdbarch), watch_hi_addr = 0;
   struct watch_area *area;
 
   tid = TIDGET (ptid);
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -1265,7 +1265,8 @@ s390_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   struct s390_prologue_data data;
   CORE_ADDR skip_pc;
-  skip_pc = s390_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
+  skip_pc = s390_analyze_prologue (gdbarch, pc, addr_minus_one (gdbarch),
+				   &data);
   return skip_pc ? skip_pc : pc;
 }
 
@@ -1510,7 +1511,8 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
 	  struct s390_prologue_data data2;
 	  pv_t *sp = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM];
 
-	  if (!(s390_analyze_prologue (gdbarch, func, (CORE_ADDR)-1, &data2)
+	  if (!(s390_analyze_prologue (gdbarch, func, addr_minus_one (gdbarch),
+				       &data2)
 	        && pv_is_register (*sp, S390_SP_REGNUM)
 	        && sp->k != 0))
 	    return 0;
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -874,7 +874,7 @@ score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
 
   char *memblock = NULL;
   char *memblock_ptr = NULL;
-  CORE_ADDR prev_pc = -1;
+  CORE_ADDR prev_pc = addr_minus_one (gdbarch);
 
   /* Allocate MEMBLOCK if PC - STARTADDR > 0.  */
   memblock_ptr = memblock =
@@ -1067,10 +1067,11 @@ score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
                         struct frame_info *this_frame,
                         struct score_frame_cache *this_cache)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   CORE_ADDR sp;
   CORE_ADDR fp;
   CORE_ADDR cur_pc = startaddr;
-  enum bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (this_frame));
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   int sp_offset = 0;
   int ra_offset = 0;
@@ -1079,7 +1080,7 @@ score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
   int fp_offset_p = 0;
   int inst_len = 0;
 
-  CORE_ADDR prev_pc = -1;
+  CORE_ADDR prev_pc = addr_minus_one (gdbarch);
 
   sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
   fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -746,7 +746,8 @@ sh_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
     return max (pc, start_pc);
 
   cache.sp_offset = -4;
-  pc = sh_analyze_prologue (gdbarch, start_pc, (CORE_ADDR) -1, &cache, 0);
+  pc = sh_analyze_prologue (gdbarch, start_pc, addr_minus_one (gdbarch), &cache,
+			    0);
   if (!cache.uses_fp)
     return start_pc;
 
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -923,7 +923,9 @@ frv_relocate_main_executable (void)
 
   ALL_OBJFILE_OSECTIONS (symfile_objfile, osect)
     {
-      CORE_ADDR orig_addr, addr, offset;
+      struct gdbarch *gdbarch = get_objfile_arch (symfile_objfile);
+      CORE_ADDR orig_addr, addr;
+      addr_offset_t offset;
       int osect_idx;
       int seg;
       
@@ -934,17 +936,18 @@ frv_relocate_main_executable (void)
       /* Offset from where this section started.  */
       offset = ANOFFSET (symfile_objfile->section_offsets, osect_idx);
       /* Original address prior to any past relocations.  */
-      orig_addr = addr - offset;
+      orig_addr = addr_sub_offset (gdbarch, addr, offset);
 
       for (seg = 0; seg < ldm->nsegs; seg++)
 	{
 	  if (ldm->segs[seg].p_vaddr <= orig_addr
 	      && orig_addr < ldm->segs[seg].p_vaddr + ldm->segs[seg].p_memsz)
 	    {
-	      new_offsets->offsets[osect_idx]
-		= ldm->segs[seg].addr - ldm->segs[seg].p_vaddr;
+	      new_offsets->offsets[osect_idx] = addr_sub_to_offset (gdbarch,
+							ldm->segs[seg].addr,
+							ldm->segs[seg].p_vaddr);
 
-	      if (new_offsets->offsets[osect_idx] != offset)
+	      if (new_offsets->offsets[osect_idx].a != offset.a)
 		changed = 1;
 	      break;
 	    }
--- a/gdb/solib-som.c
+++ b/gdb/solib-som.c
@@ -842,12 +842,13 @@ som_solib_section_offsets (struct objfile *objfile,
          is valid.  The BFDs will never match.  Make a best guess.  */
       if (strstr (objfile->name, so_list->so_name))
 	{
+	  struct gdbarch *gdbarch = get_objfile_arch (so_list->objfile);
 	  asection *private_section;
 
 	  /* The text offset is easy.  */
 	  offsets->offsets[SECT_OFF_TEXT (objfile)]
-	    = (so_list->lm_info->text_addr
-	       - so_list->lm_info->text_link_addr);
+	    = addr_sub_to_offset (gdbarch, so_list->lm_info->text_addr,
+				  so_list->lm_info->text_link_addr);
 	  offsets->offsets[SECT_OFF_RODATA (objfile)]
 	    = ANOFFSET (offsets, SECT_OFF_TEXT (objfile));
 
@@ -858,12 +859,13 @@ som_solib_section_offsets (struct objfile *objfile,
 	  if (!private_section)
 	    {
 	      warning (_("Unable to find $PRIVATE$ in shared library!"));
-	      offsets->offsets[SECT_OFF_DATA (objfile)] = 0;
-	      offsets->offsets[SECT_OFF_BSS (objfile)] = 0;
+	      offsets->offsets[SECT_OFF_DATA (objfile)].a = 0;
+	      offsets->offsets[SECT_OFF_BSS (objfile)].a = 0;
 	      return 1;
 	    }
 	  offsets->offsets[SECT_OFF_DATA (objfile)]
-	    = (so_list->lm_info->data_start - private_section->vma);
+	    = addr_sub_to_offset (gdbarch, so_list->lm_info->data_start,
+				  private_section->vma);
 	  offsets->offsets[SECT_OFF_BSS (objfile)]
 	    = ANOFFSET (offsets, SECT_OFF_DATA (objfile));
 	  return 1;
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -50,17 +50,19 @@
 static void
 spu_relocate_main_executable (int spufs_fd)
 {
+  struct gdbarch *gdbarch;
   struct section_offsets *new_offsets;
   int i;
 
   if (symfile_objfile == NULL)
     return;
+  gdbarch = get_objfile_arch (symfile_objfile);
 
   new_offsets = alloca (symfile_objfile->num_sections
 			* sizeof (struct section_offsets));
 
   for (i = 0; i < symfile_objfile->num_sections; i++)
-    new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
+    new_offsets->offsets[i] = addr_to_offset (gdbarch, SPUADDR (spufs_fd, 0));
 
   objfile_relocate (symfile_objfile, new_offsets);
 }
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -173,7 +173,7 @@ LM_DYNAMIC_FROM_LINK_MAP (struct so_list *so)
 static CORE_ADDR
 LM_ADDR_CHECK (struct so_list *so, bfd *abfd)
 {
-  if (so->lm_info->l_addr == (CORE_ADDR)-1)
+  if (so->lm_info->l_addr == addr_minus_one (target_gdbarch))
     {
       struct bfd_section *dyninfo_sect;
       CORE_ADDR l_addr, l_dynaddr, dynaddr, align = 0x1000;
@@ -918,7 +918,7 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
   old_chain = make_cleanup (xfree, new);
   new->lm_info = xmalloc (sizeof (struct lm_info));
   make_cleanup (xfree, new->lm_info);
-  new->lm_info->l_addr = (CORE_ADDR)-1;
+  new->lm_info->l_addr = addr_minus_one (target_gdbarch);
   new->lm_info->lm_addr = ldsomap;
   new->lm_info->lm = xzalloc (lmo->link_map_size);
   make_cleanup (xfree, new->lm_info->lm);
@@ -1095,7 +1095,7 @@ svr4_current_sos (void)
       new->lm_info = xmalloc (sizeof (struct lm_info));
       make_cleanup (xfree, new->lm_info);
 
-      new->lm_info->l_addr = (CORE_ADDR)-1;
+      new->lm_info->l_addr = addr_minus_one (target_gdbarch);
       new->lm_info->lm_addr = lm;
       new->lm_info->lm = xzalloc (lmo->link_map_size);
       make_cleanup (xfree, new->lm_info->lm);
@@ -1343,17 +1343,19 @@ enable_break (struct svr4_info *info, int from_tty)
 	  /* Record the relocated start and end address of the dynamic linker
 	     text and plt section for svr4_in_dynsym_resolve_code.  */
 	  bfd *tmp_bfd;
-	  CORE_ADDR load_addr;
+	  addr_offset_t load_offset;
 
 	  tmp_bfd = os->objfile->obfd;
-	  load_addr = ANOFFSET (os->objfile->section_offsets,
-				os->objfile->sect_index_text);
+	  load_offset = ANOFFSET (os->objfile->section_offsets,
+				  os->objfile->sect_index_text);
 
 	  interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
 	  if (interp_sect)
 	    {
 	      info->interp_text_sect_low =
-		bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+		addr_add_offset (get_objfile_arch (os->objfile),
+				 bfd_section_vma (tmp_bfd, interp_sect),
+				 load_offset);
 	      info->interp_text_sect_high =
 		info->interp_text_sect_low
 		+ bfd_section_size (tmp_bfd, interp_sect);
@@ -1362,7 +1364,9 @@ enable_break (struct svr4_info *info, int from_tty)
 	  if (interp_sect)
 	    {
 	      info->interp_plt_sect_low =
-		bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+		addr_add_offset (get_objfile_arch (os->objfile),
+				 bfd_section_vma (tmp_bfd, interp_sect),
+				 load_offset);
 	      info->interp_plt_sect_high =
 		info->interp_plt_sect_low
 		+ bfd_section_size (tmp_bfd, interp_sect);
@@ -1378,8 +1382,8 @@ enable_break (struct svr4_info *info, int from_tty)
   interp_name = find_program_interpreter ();
   if (interp_name)
     {
-      CORE_ADDR load_addr = 0;
-      int load_addr_found = 0;
+      addr_offset_t load_offset = { 0 };
+      int load_offset_found = 0;
       int loader_found_in_list = 0;
       struct so_list *so;
       bfd *tmp_bfd = NULL;
@@ -1416,9 +1420,10 @@ enable_break (struct svr4_info *info, int from_tty)
 	{
 	  if (svr4_same_1 (interp_name, so->so_original_name))
 	    {
-	      load_addr_found = 1;
+	      load_offset_found = 1;
 	      loader_found_in_list = 1;
-	      load_addr = LM_ADDR_CHECK (so, tmp_bfd);
+	      load_offset = addr_to_offset (target_gdbarch,
+					    LM_ADDR_CHECK (so, tmp_bfd));
 	      break;
 	    }
 	  so = so->next;
@@ -1426,9 +1431,16 @@ enable_break (struct svr4_info *info, int from_tty)
 
       /* If we were not able to find the base address of the loader
          from our so_list, then try using the AT_BASE auxilliary entry.  */
-      if (!load_addr_found)
-        if (target_auxv_search (&current_target, AT_BASE, &load_addr) > 0)
-          load_addr_found = 1;
+      if (!load_offset_found)
+	{
+	  CORE_ADDR load_addr;
+
+	  if (target_auxv_search (&current_target, AT_BASE, &load_addr) > 0)
+	    {
+	      load_offset_found = 1;
+	      load_offset = addr_to_offset (target_gdbarch, load_addr);
+	    }
+	}
 
       /* Otherwise we find the dynamic linker's base address by examining
 	 the current pc (which should point at the entry point for the
@@ -1437,19 +1449,21 @@ enable_break (struct svr4_info *info, int from_tty)
          This is more fragile than the previous approaches, but is a good
          fallback method because it has actually been working well in
          most cases.  */
-      if (!load_addr_found)
+      if (!load_offset_found)
 	{
 	  struct regcache *regcache
 	    = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
-	  load_addr = (regcache_read_pc (regcache)
-		       - exec_entry_point (tmp_bfd, tmp_bfd_target));
+	  load_offset = addr_sub_to_offset (target_gdbarch,
+					    regcache_read_pc (regcache),
+					    exec_entry_point (tmp_bfd,
+							      tmp_bfd_target));
 	}
 
       if (!loader_found_in_list)
 	{
 	  info->debug_loader_name = xstrdup (interp_name);
 	  info->debug_loader_offset_p = 1;
-	  info->debug_loader_offset = load_addr;
+	  info->debug_loader_offset = load_offset.a;
 	  solib_add (NULL, from_tty, &current_target, auto_solib_add);
 	}
 
@@ -1459,7 +1473,9 @@ enable_break (struct svr4_info *info, int from_tty)
       if (interp_sect)
 	{
 	  info->interp_text_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+	    addr_add_offset (target_gdbarch,
+			     bfd_section_vma (tmp_bfd, interp_sect),
+			     load_offset);
 	  info->interp_text_sect_high =
 	    info->interp_text_sect_low
 	    + bfd_section_size (tmp_bfd, interp_sect);
@@ -1468,7 +1484,9 @@ enable_break (struct svr4_info *info, int from_tty)
       if (interp_sect)
 	{
 	  info->interp_plt_sect_low =
-	    bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+	    addr_add_offset (target_gdbarch,
+			     bfd_section_vma (tmp_bfd, interp_sect),
+			     load_offset);
 	  info->interp_plt_sect_high =
 	    info->interp_plt_sect_low
 	    + bfd_section_size (tmp_bfd, interp_sect);
@@ -1496,7 +1514,9 @@ enable_break (struct svr4_info *info, int from_tty)
 
       if (sym_addr != 0)
 	{
-	  create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr);
+	  sym_addr = addr_add_offset (target_gdbarch, sym_addr, load_offset);
+
+	  create_solib_event_breakpoint (target_gdbarch, sym_addr);
 	  xfree (interp_name);
 	  return 1;
 	}
@@ -1679,6 +1699,7 @@ svr4_relocate_main_executable (void)
 
   if (symfile_objfile)
     {
+      struct gdbarch *gdbarch = get_objfile_arch (symfile_objfile);
       struct section_offsets *new_offsets;
       int i;
 
@@ -1686,18 +1707,21 @@ svr4_relocate_main_executable (void)
 			    * sizeof (*new_offsets));
 
       for (i = 0; i < symfile_objfile->num_sections; i++)
-	new_offsets->offsets[i] = displacement;
+	new_offsets->offsets[i] = addr_to_offset (gdbarch, displacement);
 
       objfile_relocate (symfile_objfile, new_offsets);
     }
   else if (exec_bfd)
     {
       asection *asect;
+      addr_offset_t offset = addr_to_offset (target_gdbarch, displacement);
 
       for (asect = exec_bfd->sections; asect != NULL; asect = asect->next)
 	exec_set_section_address (bfd_get_filename (exec_bfd), asect->index,
-				  (bfd_section_vma (exec_bfd, asect)
-				   + displacement));
+				  addr_add_offset (target_gdbarch,
+						   bfd_section_vma (exec_bfd,
+								    asect),
+						   offset));
     }
 }
 
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -330,8 +330,9 @@ static void
 solib_target_relocate_section_addresses (struct so_list *so,
 					 struct target_section *sec)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (so->objfile);
   int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
-  CORE_ADDR offset;
+  addr_offset_t offset;
 
   /* Build the offset table only once per object file.  We can not do
      it any earlier, since we need to open the file first.  */
@@ -367,7 +368,7 @@ Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
 	      section_bases = VEC_address (CORE_ADDR,
 					   so->lm_info->section_bases);
 
-	      so->addr_low = ~(CORE_ADDR) 0;
+	      so->addr_low = addr_minus_one (gdbarch);
 	      so->addr_high = 0;
 	      for (i = 0, sect = so->abfd->sections;
 		   sect != NULL;
@@ -388,7 +389,8 @@ Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
 		      gdb_assert (so->addr_low <= so->addr_high);
 		      found_range = 1;
 		    }
-		  so->lm_info->offsets->offsets[i] = section_bases[bases_index];
+		  so->lm_info->offsets->offsets[i] = addr_to_offset (gdbarch,
+						    section_bases[bases_index]);
 		  bases_index++;
 		}
 	      if (!found_range)
@@ -414,7 +416,7 @@ Could not relocate shared library \"%s\": no segments"), so->so_name);
 	      segment_bases = VEC_address (CORE_ADDR,
 					   so->lm_info->segment_bases);
 
-	      if (!symfile_map_offsets_to_segments (so->abfd, data,
+	      if (!symfile_map_offsets_to_segments (gdbarch, so->abfd, data,
 						    so->lm_info->offsets,
 						    num_bases, segment_bases))
 		warning (_("\
@@ -451,8 +453,8 @@ Could not relocate shared library \"%s\": bad offsets"), so->so_name);
     }
 
   offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
-  sec->addr += offset;
-  sec->endaddr += offset;
+  sec->addr = addr_add_offset (gdbarch, sec->addr, offset);
+  sec->endaddr = addr_add_offset (gdbarch, sec->endaddr, offset);
 }
 
 static int
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -803,7 +803,7 @@ static CORE_ADDR
 spu_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   struct spu_prologue_data data;
-  return spu_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
+  return spu_analyze_prologue (gdbarch, pc, addr_minus_one (gdbarch), &data);
 }
 
 /* Return the frame pointer in use at address PC.  */
@@ -812,7 +812,7 @@ spu_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc,
 			   int *reg, LONGEST *offset)
 {
   struct spu_prologue_data data;
-  spu_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
+  spu_analyze_prologue (gdbarch, pc, addr_minus_one (gdbarch), &data);
 
   if (data.size != -1 && data.cfa_reg != -1)
     {
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -69,18 +69,21 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
   struct objfile *objf;
   struct bfd *nbfd;
   struct bfd_section *sec;
-  bfd_vma loadbase;
+  bfd_vma load_vma;
+  addr_offset_t load_offset;
   struct section_addr_info *sai;
   unsigned int i;
 
   if (bfd_get_flavour (templ) != bfd_target_elf_flavour)
     error (_("add-symbol-file-from-memory not supported for this target"));
 
-  nbfd = bfd_elf_bfd_from_remote_memory (templ, addr, &loadbase,
+  nbfd = bfd_elf_bfd_from_remote_memory (templ, addr, &load_vma,
 					 target_read_memory);
   if (nbfd == NULL)
     error (_("Failed to read a valid object file image from memory."));
 
+  load_offset = addr_to_offset (target_gdbarch, load_vma);
+
   if (name == NULL)
     nbfd->filename = xstrdup ("shared object read from target memory");
   else
@@ -102,7 +105,9 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
-	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
+	sai->other[i].addr = addr_add_offset (target_gdbarch,
+					      bfd_get_section_vma (nbfd, sec),
+					      load_offset);
 	sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec);
 	sai->other[i].sectindex = sec->index;
 	++i;
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -359,16 +359,12 @@ build_section_addr_info_from_section_table (const struct target_section *start,
 /* Create a section_addr_info from section offsets in OBJFILE.  */
 
 struct section_addr_info *
-build_section_addr_info_from_objfile (const struct objfile *objfile)
+build_section_addr_info_from_objfile (struct objfile *objfile)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct section_addr_info *sap;
   int i;
   struct bfd_section *sec;
-  int addr_bit = gdbarch_addr_bit (objfile->gdbarch);
-  CORE_ADDR mask = CORE_ADDR_MAX;
-
-  if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
-    mask = ((CORE_ADDR) 1 << addr_bit) - 1;
 
   sap = alloc_section_addr_info (objfile->num_sections);
   for (i = 0, sec = objfile->obfd->sections;
@@ -376,8 +372,10 @@ build_section_addr_info_from_objfile (const struct objfile *objfile)
        i++, sec = sec->next)
     {
       gdb_assert (sec != NULL);
-      sap->other[i].addr = (bfd_get_section_vma (objfile->obfd, sec)
-                            + objfile->section_offsets->offsets[i]) & mask;
+      sap->other[i].addr = addr_add_offset (gdbarch,
+					    bfd_get_section_vma (objfile->obfd,
+								 sec),
+					  objfile->section_offsets->offsets[i]);
       sap->other[i].name = xstrdup (bfd_get_section_name (objfile->obfd, sec));
       sap->other[i].sectindex = sec->index;
     }
@@ -441,7 +439,7 @@ init_objfile_sect_indices (struct objfile *objfile)
 
   for (i = 0; i < objfile->num_sections; i++)
     {
-      if (ANOFFSET (objfile->section_offsets, i) != 0)
+      if (ANOFFSET (objfile->section_offsets, i).a != 0)
 	{
 	  break;
 	}
@@ -463,6 +461,7 @@ init_objfile_sect_indices (struct objfile *objfile)
 
 struct place_section_arg
 {
+  struct gdbarch *gdbarch;
   struct section_offsets *offsets;
   CORE_ADDR lowest;
 };
@@ -474,7 +473,9 @@ static void
 place_section (bfd *abfd, asection *sect, void *obj)
 {
   struct place_section_arg *arg = obj;
-  CORE_ADDR *offsets = arg->offsets->offsets, start_addr;
+  struct gdbarch *gdbarch = arg->gdbarch;
+  addr_offset_t *offsets = arg->offsets->offsets;
+  CORE_ADDR start_addr;
   int done;
   ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect);
 
@@ -483,7 +484,7 @@ place_section (bfd *abfd, asection *sect, void *obj)
     return;
 
   /* If the user specified an offset, honor it.  */
-  if (offsets[sect->index] != 0)
+  if (offsets[sect->index].a != 0)
     return;
 
   /* Otherwise, let's try to find a place for the section.  */
@@ -510,14 +511,14 @@ place_section (bfd *abfd, asection *sect, void *obj)
 	/* If the section offset is 0, either the section has not been placed
 	   yet, or it was the lowest section placed (in which case LOWEST
 	   will be past its end).  */
-	if (offsets[indx] == 0)
+	if (offsets[indx].a == 0)
 	  continue;
 
 	/* If this section would overlap us, then we must move up.  */
-	if (start_addr + bfd_get_section_size (sect) > offsets[indx]
-	    && start_addr < offsets[indx] + bfd_get_section_size (cur_sec))
+	if (start_addr + bfd_get_section_size (sect) > offsets[indx].a
+	    && start_addr < offsets[indx].a + bfd_get_section_size (cur_sec))
 	  {
-	    start_addr = offsets[indx] + bfd_get_section_size (cur_sec);
+	    start_addr = offsets[indx].a + bfd_get_section_size (cur_sec);
 	    start_addr = (start_addr + align - 1) & -align;
 	    done = 0;
 	    break;
@@ -528,7 +529,7 @@ place_section (bfd *abfd, asection *sect, void *obj)
     }
   while (!done);
 
-  offsets[sect->index] = start_addr;
+  offsets[sect->index] = addr_to_offset (gdbarch, start_addr);
   arg->lowest = start_addr + bfd_get_section_size (sect);
 }
 
@@ -537,7 +538,8 @@ place_section (bfd *abfd, asection *sect, void *obj)
    entries.  */
 
 void
-relative_addr_info_to_section_offsets (struct section_offsets *section_offsets,
+relative_addr_info_to_section_offsets (struct gdbarch *gdbarch,
+				       struct section_offsets *section_offsets,
 				       int num_sections,
 				       struct section_addr_info *addrs)
 {
@@ -557,7 +559,8 @@ relative_addr_info_to_section_offsets (struct section_offsets *section_offsets,
       /* Record all sections in offsets */
       /* The section_offsets in the objfile are here filled in using
          the BFD index. */
-      section_offsets->offsets[osp->sectindex] = osp->addr;
+      section_offsets->offsets[osp->sectindex] = addr_to_offset (gdbarch,
+								 osp->addr);
     }
 }
 
@@ -565,7 +568,8 @@ relative_addr_info_to_section_offsets (struct section_offsets *section_offsets,
    also SECTINDEXes there.  */
 
 void
-addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
+addr_info_make_relative (struct gdbarch *gdbarch,
+			 struct section_addr_info *addrs, bfd *abfd)
 {
   asection *lower_sect;
   asection *sect;
@@ -604,8 +608,12 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
 	  sect = bfd_get_section_by_name (abfd, addrs->other[i].name);
 	  if (sect)
 	    {
-	      addrs->other[i].addr -= bfd_section_vma (abfd, sect);
-	      lower_offset = addrs->other[i].addr;
+	      addr_offset_t offset;
+
+	      offset = addr_sub_to_offset (gdbarch, addrs->other[i].addr,
+					   bfd_section_vma (abfd, sect));
+	      addrs->other[i].addr = offset.a;
+	      lower_offset = offset.a;
 	      /* This is the index used by BFD. */
 	      addrs->other[i].sectindex = sect->index;
 	    }
@@ -631,11 +639,13 @@ void
 default_symfile_offsets (struct objfile *objfile,
 			 struct section_addr_info *addrs)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
   objfile->num_sections = bfd_count_sections (objfile->obfd);
   objfile->section_offsets = (struct section_offsets *)
     obstack_alloc (&objfile->objfile_obstack,
 		   SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
-  relative_addr_info_to_section_offsets (objfile->section_offsets,
+  relative_addr_info_to_section_offsets (gdbarch, objfile->section_offsets,
 					 objfile->num_sections, addrs);
 
   /* For relocatable files, all loadable sections will start at zero.
@@ -658,10 +668,11 @@ default_symfile_offsets (struct objfile *objfile,
 
       if (cur_sec == NULL)
 	{
-	  CORE_ADDR *offsets = objfile->section_offsets->offsets;
+	  addr_offset_t *offsets = objfile->section_offsets->offsets;
 
 	  /* Pick non-overlapping offsets for sections the user did not
 	     place explicitly.  */
+	  arg.gdbarch = gdbarch;
 	  arg.offsets = objfile->section_offsets;
 	  arg.lowest = 0;
 	  bfd_map_over_sections (objfile->obfd, place_section, &arg);
@@ -698,10 +709,10 @@ default_symfile_offsets (struct objfile *objfile,
 	      if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
 		continue;
 
-	      bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+	      bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index].a);
 	      exec_set_section_address (bfd_get_filename (abfd), cur_sec->index,
-					offsets[cur_sec->index]);
-	      offsets[cur_sec->index] = 0;
+					offsets[cur_sec->index].a);
+	      offsets[cur_sec->index].a = 0;
 	    }
 	}
     }
@@ -813,6 +824,7 @@ syms_from_objfile (struct objfile *objfile,
                    int num_offsets,
 		   int add_flags)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct section_addr_info *local_addr = NULL;
   struct cleanup *old_chain;
   const int mainline = add_flags & SYMFILE_MAINLINE;
@@ -834,8 +846,7 @@ syms_from_objfile (struct objfile *objfile,
      no load address was specified. */
   if (! addrs && ! offsets)
     {
-      local_addr
-	= alloc_section_addr_info (bfd_count_sections (objfile->obfd));
+      local_addr = alloc_section_addr_info (bfd_count_sections (objfile->obfd));
       make_cleanup (xfree, local_addr);
       addrs = local_addr;
     }
@@ -871,7 +882,7 @@ syms_from_objfile (struct objfile *objfile,
      We no longer warn if the lowest section is not a text segment (as
      happens for the PA64 port.  */
   if (addrs && addrs->other[0].name)
-    addr_info_make_relative (addrs, objfile->obfd);
+    addr_info_make_relative (gdbarch, addrs, objfile->obfd);
 
   /* Initialize symbol reading routines for this objfile, allow complaints to
      appear for this new file, and record how verbose to be, then do the
@@ -3006,15 +3017,19 @@ pc_in_unmapped_range (CORE_ADDR pc, struct obj_section *section)
 {
   if (section_is_overlay (section))
     {
+      struct gdbarch *gdbarch = get_objfile_arch (section->objfile);
       bfd *abfd = section->objfile->obfd;
       asection *bfd_section = section->the_bfd_section;
 
       /* We assume the LMA is relocated by the same offset as the VMA.  */
       bfd_vma size = bfd_get_section_size (bfd_section);
-      CORE_ADDR offset = obj_section_offset (section);
+      addr_offset_t offset = obj_section_offset (section);
+
+      CORE_ADDR lma = addr_add_offset (gdbarch,
+				       bfd_get_section_lma (abfd, bfd_section),
+				       offset);
 
-      if (bfd_get_section_lma (abfd, bfd_section) + offset <= pc
-	  && pc < bfd_get_section_lma (abfd, bfd_section) + offset + size)
+      if (lma <= pc && pc < lma + size)
 	return 1;
     }
 
@@ -3707,7 +3722,8 @@ free_symfile_segment_data (struct symfile_segment_data *data)
    not be able to distinguish between an empty data segment and a
    missing data segment; a missing text segment is less plausible.  */
 int
-symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
+symfile_map_offsets_to_segments (struct gdbarch *gdbarch, bfd *abfd,
+				 struct symfile_segment_data *data,
 				 struct section_offsets *offsets,
 				 int num_segment_bases,
 				 const CORE_ADDR *segment_bases)
@@ -3740,8 +3756,9 @@ symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
       if (which > num_segment_bases)
         which = num_segment_bases;
 
-      offsets->offsets[i] = (segment_bases[which - 1]
-                             - data->segment_bases[which - 1]);
+      offsets->offsets[i] = addr_sub_to_offset (gdbarch,
+						segment_bases[which - 1],
+						data->segment_bases[which - 1]);
     }
 
   return 1;
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -182,13 +182,15 @@ struct sym_fns
 };
 
 extern struct section_addr_info *
-	   build_section_addr_info_from_objfile (const struct objfile *objfile);
+		 build_section_addr_info_from_objfile (struct objfile *objfile);
 
-extern void relative_addr_info_to_section_offsets
-  (struct section_offsets *section_offsets, int num_sections,
-   struct section_addr_info *addrs);
+extern void relative_addr_info_to_section_offsets (struct gdbarch *gdbarch,
+					struct section_offsets *section_offsets,
+						   int num_sections,
+					       struct section_addr_info *addrs);
 
-extern void addr_info_make_relative (struct section_addr_info *addrs,
+extern void addr_info_make_relative (struct gdbarch *gdbarch,
+				     struct section_addr_info *addrs,
 				     bfd *abfd);
 
 /* The default version of sym_fns.sym_offsets for readers that don't
@@ -265,8 +267,7 @@ extern char *find_separate_debug_file_by_debuglink (struct objfile *);
 
 /* Create a new section_addr_info, with room for NUM_SECTIONS.  */
 
-extern struct section_addr_info *alloc_section_addr_info (size_t
-							  num_sections);
+extern struct section_addr_info *alloc_section_addr_info (size_t num_sections);
 
 /* Build (allocate and populate) a section_addr_info struct from an
    existing section table.  */
@@ -390,7 +391,7 @@ extern void simple_overlay_update (struct obj_section *);
 extern bfd_byte *symfile_relocate_debug_section (struct objfile *, asection *,
 						 bfd_byte *);
 
-extern int symfile_map_offsets_to_segments (bfd *,
+extern int symfile_map_offsets_to_segments (struct gdbarch *gdbarch, bfd *,
 					    struct symfile_segment_data *,
 					    struct section_offsets *,
 					    int, const CORE_ADDR *);
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -378,7 +378,7 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
 	fprintf_filtered (outfile, ", ");
       wrap_here ("    ");
       fputs_filtered (paddress (gdbarch,
-				ANOFFSET (psymtab->section_offsets, i)),
+				ANOFFSET (psymtab->section_offsets, i).a),
 		      outfile);
     }
   fprintf_filtered (outfile, "\n");
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1144,11 +1144,13 @@ fixup_section (struct general_symbol_info *ginfo,
       struct obj_section *s;
       ALL_OBJFILE_OSECTIONS (objfile, s)
 	{
+	  struct gdbarch *gdbarch = get_objfile_arch (objfile);
 	  int idx = s->the_bfd_section->index;
-	  CORE_ADDR offset = ANOFFSET (objfile->section_offsets, idx);
+	  addr_offset_t offset = ANOFFSET (objfile->section_offsets, idx);
 
-	  if (obj_section_addr (s) - offset <= addr
-	      && addr < obj_section_endaddr (s) - offset)
+	  if (addr_sub_offset (gdbarch, obj_section_addr (s), offset) <= addr
+	      && addr < addr_sub_offset (gdbarch, obj_section_endaddr (s),
+					 offset))
 	    {
 	      ginfo->obj_section = s;
 	      ginfo->section = idx;
@@ -4859,6 +4861,128 @@ expand_line_sal (struct symtab_and_line sal)
   return ret;
 }
 
+void
+addr_width_assert (struct gdbarch *gdbarch, ULONGEST addr)
+{
+  int addr_bit = gdbarch_addr_bit (gdbarch);
+
+  if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
+    gdb_assert ((addr & -((ULONGEST) 1 << addr_bit)) == 0);
+}
+
+void
+addr_width_check_error (struct gdbarch *gdbarch, ULONGEST addr)
+{
+  int addr_bit = gdbarch_addr_bit (gdbarch);
+
+  if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT)
+      && (addr & -((ULONGEST) 1 << addr_bit)) != 0)
+    error (_("Address %s does not fit the architecture %s size %d bits"),
+	   hex_string (addr), gdbarch_bfd_arch_info (gdbarch)->printable_name,
+	   addr_bit);
+}
+
+CORE_ADDR
+addr_width_clear (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  int addr_bit = gdbarch_addr_bit (gdbarch);
+
+  if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
+    addr &= ((ULONGEST) 1 << addr_bit) - 1;
+
+  return addr;
+}
+
+CORE_ADDR
+addr_add_offset (struct gdbarch *gdbarch, CORE_ADDR addr, addr_offset_t offset)
+{
+  addr_width_assert (gdbarch, addr);
+  addr_width_assert (gdbarch, offset.a);
+
+  addr += offset.a;
+
+  addr = addr_width_clear (gdbarch, addr);
+
+  return addr;
+}
+
+CORE_ADDR
+addr_sub_offset (struct gdbarch *gdbarch, CORE_ADDR addr, addr_offset_t offset)
+{
+  addr_width_assert (gdbarch, addr);
+  addr_width_assert (gdbarch, offset.a);
+
+  addr -= offset.a;
+
+  addr = addr_width_clear (gdbarch, addr);
+
+  return addr;
+}
+
+addr_offset_t
+addr_to_offset (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  addr_offset_t retval;
+
+  addr_width_assert (gdbarch, addr);
+
+  retval.a = addr;
+
+  return retval;
+}
+
+addr_offset_t
+addr_sub_to_offset (struct gdbarch *gdbarch, CORE_ADDR addr1, CORE_ADDR addr2)
+{
+  addr_offset_t retval;
+
+  addr_width_assert (gdbarch, addr1);
+  addr_width_assert (gdbarch, addr2);
+
+  retval.a = addr1 - addr2;
+
+  retval.a = addr_width_clear (gdbarch, retval.a);
+
+  return retval;
+}
+
+addr_offset_t
+addr_offset_add (struct gdbarch *gdbarch, addr_offset_t offset1, addr_offset_t offset2)
+{
+  addr_width_assert (gdbarch, offset1.a);
+  addr_width_assert (gdbarch, offset2.a);
+
+  offset1.a += offset2.a;
+
+  offset1.a = addr_width_clear (gdbarch, offset1.a);
+
+  return offset1;
+}
+
+addr_offset_t
+addr_offset_sub (struct gdbarch *gdbarch, addr_offset_t offset1, addr_offset_t offset2)
+{
+  addr_width_assert (gdbarch, offset1.a);
+  addr_width_assert (gdbarch, offset2.a);
+
+  offset1.a -= offset2.a;
+
+  offset1.a = addr_width_clear (gdbarch, offset1.a);
+
+  return offset1;
+}
+
+const addr_offset_t dummy_addr_offset;
+
+CORE_ADDR
+addr_minus_one (struct gdbarch *gdbarch)
+{
+  CORE_ADDR retval = -1;
+
+  retval = addr_width_clear (gdbarch, retval);
+
+  return retval;
+}
 
 void
 _initialize_symtab (void)
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -701,6 +701,35 @@ struct linetable
   struct linetable_entry item[1];
 };
 
+extern void addr_width_assert (struct gdbarch *gdbarch, ULONGEST addr);
+
+extern void addr_width_check_error (struct gdbarch *gdbarch, ULONGEST addr);
+
+extern CORE_ADDR addr_width_clear (struct gdbarch *gdbarch, CORE_ADDR addr);
+
+extern CORE_ADDR addr_add_offset (struct gdbarch *gdbarch, CORE_ADDR addr,
+				  addr_offset_t offset);
+
+extern CORE_ADDR addr_sub_offset (struct gdbarch *gdbarch, CORE_ADDR addr,
+				  addr_offset_t offset);
+
+extern addr_offset_t addr_to_offset (struct gdbarch *gdbarch, CORE_ADDR addr);
+
+extern addr_offset_t addr_sub_to_offset (struct gdbarch *gdbarch,
+					 CORE_ADDR addr1, CORE_ADDR addr2);
+
+extern addr_offset_t addr_offset_add (struct gdbarch *gdbarch,
+				      addr_offset_t offset1,
+				      addr_offset_t offset2);
+
+extern addr_offset_t addr_offset_sub (struct gdbarch *gdbarch,
+				      addr_offset_t offset1,
+				      addr_offset_t offset2);
+
+extern const addr_offset_t dummy_addr_offset;
+
+extern CORE_ADDR addr_minus_one (struct gdbarch *gdbarch);
+
 /* How to relocate the symbols from each section in a symbol file.
    Each struct contains an array of offsets.
    The ordering and meaning of the offsets is file-type-dependent;
@@ -713,12 +742,13 @@ struct linetable
 
 struct section_offsets
 {
-  CORE_ADDR offsets[1];		/* As many as needed. */
+  addr_offset_t offsets[1];		/* As many as needed. */
 };
 
 #define	ANOFFSET(secoff, whichone) \
    ((whichone == -1) \
-    ? (internal_error (__FILE__, __LINE__, _("Section index is uninitialized")), -1) \
+    ? (internal_error (__FILE__, __LINE__, _("Section index is uninitialized")), \
+       dummy_addr_offset)							 \
     : secoff->offsets[whichone])
 
 /* The size of a section_offsets table for N sections.  */
--- a/gdb/testsuite/gdb.base/long_long.exp
+++ b/gdb/testsuite/gdb.base/long_long.exp
@@ -177,7 +177,7 @@ gdb_test "p/d val.oct" "-6399925985474168457"
 gdb_test "p/u val.oct" "12046818088235383159"
 gdb_test "p/o val.oct" ""
 gdb_test "p/t val.oct" "1010011100101110111001010011100101110111000001010011100101110111"
-gdb_test_ptr "p/a val.oct" "" "" "0x77053977" "0xa72ee53977053977"
+gdb_test_ptr "p/a val.oct" "" "" "Address 0xa72ee53977053977 does not fit the architecture .* size 32 bits" "0xa72ee53977053977"
 gdb_test "p/c val.oct" "'w'"
 
 if { $sizeof_double == 8 || $sizeof_long_double == 8 } {
@@ -245,7 +245,7 @@ gdb_test_long_long "p/d *(long long *)ll" "" "" "" "81985529216486895"
 gdb_test_long_long "p/u *(long long *)ll" "" "" "" "81985529216486895"
 gdb_test_long_long "p/o *(long long *)ll" "" "" "" "04432126361152746757"
 gdb_test_long_long "p/t *(long long *)ll" "" "" "" "100100011010001010110011110001001101010111100110111101111"
-gdb_test_ptr "p/a *(long long *)ll" "" "" "0x89abcdef" "0x123456789abcdef"
+gdb_test_ptr "p/a *(long long *)ll" "" "" "Address 0x123456789abcdef does not fit the architecture .* size 32 bits" "0x123456789abcdef"
 gdb_test_long_long "p/f *(long long *)ll" "" "" "" "3.5127005640885037e-303"
 gdb_test_long_long "p/c *(long long *)ll" "" "" "" "-17 '.*'"
 
@@ -315,7 +315,7 @@ gdb_test "x/2gd g" "81985529216486895.*-6399925985474168457"
 gdb_test "x/2gu g" "81985529216486895.*12046818088235383159"
 gdb_test "x/2go g" "04432126361152746757.*01234567123456701234567"
 gdb_test "x/2gt g" "0000000100100011010001010110011110001001101010111100110111101111.*1010011100101110111001010011100101110111000001010011100101110111"
-gdb_test_ptr "x/2ga g" "" "" "0x89abcdef.*0x77053977" "0x123456789abcdef.*0xa72ee53977053977"
+gdb_test_ptr "x/2ga g" "" "" "Address 0x123456789abcdef does not fit the architecture .* size 32 bits" "0x123456789abcdef.*0xa72ee53977053977"
 gdb_test "x/2gc g" "-17 '.\[0-9\]*'.*119 'w'"
 gdb_test "x/2gf g" "3.5127005640885037e-303.*-5.9822653797615723e-120"
 
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -897,7 +897,7 @@ switch_to_thread (ptid_t ptid)
       && !is_executing (ptid))
     stop_pc = regcache_read_pc (get_thread_regcache (ptid));
   else
-    stop_pc = ~(CORE_ADDR) 0;
+    stop_pc = addr_minus_one (target_gdbarch);
 }
 
 static void
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -491,11 +491,10 @@ ui_out_field_core_addr (struct ui_out *uiout,
 			struct gdbarch *gdbarch,
 			CORE_ADDR address)
 {
-  char addstr[20];
   int addr_bit = gdbarch_addr_bit (gdbarch);
+  char addstr[20];
 
-  if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
-    address &= ((CORE_ADDR) 1 << addr_bit) - 1;
+  addr_width_assert (gdbarch, address);
 
   /* FIXME: cagney/2002-05-03: Need local_address_string() function
      that returns the language localized string formatted to a width
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -2907,16 +2907,17 @@ paddress (struct gdbarch *gdbarch, CORE_ADDR addr)
   /* Truncate address to the size of a target address, avoiding shifts
      larger or equal than the width of a CORE_ADDR.  The local
      variable ADDR_BIT stops the compiler reporting a shift overflow
-     when it won't occur. */
-  /* NOTE: This assumes that the significant address information is
+     when it won't occur.
+
+     NOTE: This assumes that the significant address information is
      kept in the least significant bits of ADDR - the upper bits were
      either zero or sign extended.  Should gdbarch_address_to_pointer or
-     some ADDRESS_TO_PRINTABLE() be used to do the conversion?  */
+     some ADDRESS_TO_PRINTABLE() be used to do the conversion?
+     
+     The value itself may be user-specified.  */
 
-  int addr_bit = gdbarch_addr_bit (gdbarch);
+  addr_width_check_error (gdbarch, addr);
 
-  if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
-    addr &= ((CORE_ADDR) 1 << addr_bit) - 1;
   return hex_string (addr);
 }
 
@@ -3029,6 +3030,9 @@ phex (ULONGEST l, int sizeof_l)
 {
   char *str;
 
+  if ((sizeof_l == 8 || sizeof_l == 4 || sizeof_l == 2) && sizeof (l) > sizeof_l)
+    gdb_assert ((l & -((ULONGEST) 1 << (8 * sizeof_l))) == 0);
+
   switch (sizeof_l)
     {
     case 8:
@@ -3058,6 +3062,9 @@ phex_nz (ULONGEST l, int sizeof_l)
 {
   char *str;
 
+  if ((sizeof_l == 8 || sizeof_l == 4 || sizeof_l == 2) && sizeof (l) > sizeof_l)
+    gdb_assert ((l & -((ULONGEST) 1 << (8 * sizeof_l))) == 0);
+
   switch (sizeof_l)
     {
     case 8:
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1658,7 +1658,7 @@ value_as_address (struct value *val)
     return gdbarch_integer_to_address (gdbarch, value_type (val),
 				       value_contents (val));
 
-  return unpack_long (value_type (val), value_contents (val));
+  return unpack_pointer (value_type (val), value_contents (val));
 #endif
 }
 \f
@@ -1796,9 +1796,27 @@ unpack_double (struct type *type, const gdb_byte *valaddr, int *invp)
 CORE_ADDR
 unpack_pointer (struct type *type, const gdb_byte *valaddr)
 {
+  struct gdbarch *gdbarch = get_type_arch (type);
+  int addr_bit = gdbarch_addr_bit (gdbarch);
+  ULONGEST retval;
+  unsigned len;
+
   /* Assume a CORE_ADDR can fit in a LONGEST (for now).  Not sure
      whether we want this to be true eventually.  */
-  return unpack_long (type, valaddr);
+  retval = unpack_long (type, valaddr);
+
+  type = check_typedef (type);
+  len = TYPE_LENGTH (type);
+
+  /* LEN for float types is unrelated to its integer bit width.  */
+  if (TYPE_CODE (type) != TYPE_CODE_FLT
+      && TYPE_CODE (type) != TYPE_CODE_DECFLOAT
+      && 8 * len <= gdbarch_addr_bit (gdbarch))
+    retval = addr_width_clear (gdbarch, retval);
+  else
+    addr_width_check_error (gdbarch, retval);
+
+  return retval;
 }
 
 \f
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -511,9 +511,8 @@ find_frame_addr_in_frame_chain (CORE_ADDR frame_addr)
 	 Truncate the frame base address in the same manner before
 	 comparing it against our argument.  */
       CORE_ADDR frame_base = get_frame_base_address (frame);
-      int addr_bit = gdbarch_addr_bit (get_frame_arch (frame));
-      if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
-	frame_base &= ((CORE_ADDR) 1 << addr_bit) - 1;
+
+      addr_width_assert (get_frame_arch (frame), frame_base);
 
       if (frame_base == frame_addr)
 	return frame;
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -809,7 +809,9 @@ enter_line_range (struct subfile *subfile, unsigned beginoffset, unsigned endoff
       addr = (int_lnno.l_lnno
 	      ? int_lnno.l_addr.l_paddr
 	      : read_symbol_nvalue (int_lnno.l_addr.l_symndx));
-      addr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+      addr = addr_add_offset (gdbarch, addr,
+			      ANOFFSET (objfile->section_offsets,
+					SECT_OFF_TEXT (objfile)));
 
       if (addr < startaddr || (endaddr && addr >= endaddr))
 	return;
@@ -923,6 +925,7 @@ static void
 read_xcoff_symtab (struct partial_symtab *pst)
 {
   struct objfile *objfile = pst->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = objfile->obfd;
   char *raw_auxptr;		/* Pointer to first raw aux entry for sym */
   char *strtbl = ((struct coff_symfile_info *) objfile->deprecated_sym_private)->strtbl;
@@ -1129,9 +1132,10 @@ read_xcoff_symtab (struct partial_symtab *pst)
 			  just_started = 0;
 			}
 
-		      file_start_addr =
-			cs->c_value + ANOFFSET (objfile->section_offsets,
-						SECT_OFF_TEXT (objfile));
+		      file_start_addr
+		        = addr_add_offset (gdbarch, cs->c_value,
+					   ANOFFSET (objfile->section_offsets,
+						     SECT_OFF_TEXT (objfile)));
 		      file_end_addr = file_start_addr + CSECT_LEN (&main_aux);
 
 		      if (cs->c_name && (cs->c_name[0] == '.'
@@ -1272,17 +1276,19 @@ read_xcoff_symtab (struct partial_symtab *pst)
 	case C_FCN:
 	  if (strcmp (cs->c_name, ".bf") == 0)
 	    {
-	      CORE_ADDR off = ANOFFSET (objfile->section_offsets,
-					SECT_OFF_TEXT (objfile));
+	      addr_offset_t off = ANOFFSET (objfile->section_offsets,
+					    SECT_OFF_TEXT (objfile));
+
 	      bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
 				    0, cs->c_naux, &main_aux);
 
 	      within_function = 1;
 
-	      new = push_context (0, fcn_start_addr + off);
+	      new = push_context (0, addr_add_offset (gdbarch, fcn_start_addr,
+						      off));
 
 	      new->name = define_symbol
-		(fcn_cs_saved.c_value + off,
+		(addr_add_offset (gdbarch, fcn_cs_saved.c_value, off),
 		 fcn_stab_saved.c_name, 0, 0, objfile);
 	      if (new->name != NULL)
 		SYMBOL_SECTION (new->name) = SECT_OFF_TEXT (objfile);
@@ -1315,10 +1321,11 @@ read_xcoff_symtab (struct partial_symtab *pst)
 
 	      finish_block (new->name, &local_symbols, new->old_blocks,
 			    new->start_addr,
-			    (fcn_cs_saved.c_value
-			     + fcn_aux_saved.x_sym.x_misc.x_fsize
-			     + ANOFFSET (objfile->section_offsets,
-					 SECT_OFF_TEXT (objfile))),
+			    addr_add_offset (gdbarch,
+			                     (fcn_cs_saved.c_value
+					  + fcn_aux_saved.x_sym.x_misc.x_fsize),
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile))),
 			    objfile);
 	      within_function = 0;
 	    }
@@ -1385,9 +1392,9 @@ read_xcoff_symtab (struct partial_symtab *pst)
 	    {
 	      depth++;
 	      new = push_context (depth,
-				  (cs->c_value
-				   + ANOFFSET (objfile->section_offsets,
-					       SECT_OFF_TEXT (objfile))));
+				  addr_add_offset (gdbarch, cs->c_value,
+					   ANOFFSET (objfile->section_offsets,
+						     SECT_OFF_TEXT (objfile))));
 	    }
 	  else if (strcmp (cs->c_name, ".eb") == 0)
 	    {
@@ -1407,9 +1414,9 @@ read_xcoff_symtab (struct partial_symtab *pst)
 		  /* Make a block for the local symbols within.  */
 		  finish_block (new->name, &local_symbols, new->old_blocks,
 				new->start_addr,
-				(cs->c_value
-				 + ANOFFSET (objfile->section_offsets,
-					     SECT_OFF_TEXT (objfile))),
+				addr_add_offset (gdbarch, cs->c_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile))),
 				objfile);
 		}
 	      local_symbols = new->locals;
@@ -1454,19 +1461,20 @@ read_xcoff_symtab (struct partial_symtab *pst)
 static struct symbol *
 process_xcoff_symbol (struct coff_symbol *cs, struct objfile *objfile)
 {
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct symbol onesymbol;
   struct symbol *sym = &onesymbol;
   struct symbol *sym2 = NULL;
   char *name, *pp;
 
   int sec;
-  CORE_ADDR off;
+  addr_offset_t off;
 
   if (cs->c_secnum < 0)
     {
       /* The value is a register number, offset within a frame, etc.,
          and does not get relocated.  */
-      off = 0;
+      off.a = 0;
       sec = -1;
     }
   else
@@ -1482,7 +1490,7 @@ process_xcoff_symbol (struct coff_symbol *cs, struct objfile *objfile)
   memset (sym, '\0', sizeof (struct symbol));
 
   /* default assumptions */
-  SYMBOL_VALUE_ADDRESS (sym) = cs->c_value + off;
+  SYMBOL_VALUE_ADDRESS (sym) = addr_add_offset (gdbarch, cs->c_value, off);
   SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
   SYMBOL_SECTION (sym) = secnum_to_section (cs->c_secnum, objfile);
 
@@ -1547,7 +1555,8 @@ process_xcoff_symbol (struct coff_symbol *cs, struct objfile *objfile)
 	case C_GSYM:
 
 	  {
-	    sym = define_symbol (cs->c_value + off, cs->c_name, 0, 0, objfile);
+	    sym = define_symbol (addr_add_offset (gdbarch, cs->c_value, off),
+				 cs->c_name, 0, 0, objfile);
 	    if (sym != NULL)
 	      {
 		SYMBOL_SECTION (sym) = sec;
@@ -1570,9 +1579,9 @@ process_xcoff_symbol (struct coff_symbol *cs, struct objfile *objfile)
 	  ++pp;
 	  if (*pp == 'V' && !within_function)
 	    *pp = 'S';
-	  sym = define_symbol ((cs->c_value
-				+ ANOFFSET (objfile->section_offsets,
-					    static_block_section)),
+	  sym = define_symbol (addr_add_offset (gdbarch, cs->c_value,
+					     ANOFFSET (objfile->section_offsets,
+						       static_block_section)),
 			       cs->c_name, 0, 0, objfile);
 	  if (sym != NULL)
 	    {
@@ -2595,7 +2604,9 @@ scan_xcoff_symtab (struct objfile *objfile)
 	    switch (p[1])
 	      {
 	      case 'S':
-		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+		symbol.n_value = addr_add_offset (gdbarch, symbol.n_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
 
 		if (gdbarch_static_transform_name_p (gdbarch))
 		  namestring = gdbarch_static_transform_name
@@ -2609,7 +2620,10 @@ scan_xcoff_symtab (struct objfile *objfile)
 		continue;
 
 	      case 'G':
-		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
+		symbol.n_value = addr_add_offset (gdbarch, symbol.n_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_DATA (objfile)));
+
 		/* The addresses in these entries are reported to be
 		   wrong.  See the code that reads 'G's for symtabs. */
 		add_psymbol_to_list (namestring, p - namestring, 1,
@@ -2747,7 +2761,9 @@ scan_xcoff_symtab (struct objfile *objfile)
 		    function_outside_compilation_unit_complaint (name);
 		    xfree (name);
 		  }
-		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		symbol.n_value = addr_add_offset (gdbarch, symbol.n_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_BLOCK,
 				     &objfile->static_psymbols,
@@ -2776,7 +2792,9 @@ scan_xcoff_symtab (struct objfile *objfile)
 		if (strncmp (namestring, "@FIX", 4) == 0)
 		  continue;
 
-		symbol.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+		symbol.n_value = addr_add_offset (gdbarch, symbol.n_value,
+					    ANOFFSET (objfile->section_offsets,
+						      SECT_OFF_TEXT (objfile)));
 		add_psymbol_to_list (namestring, p - namestring, 1,
 				     VAR_DOMAIN, LOC_BLOCK,
 				     &objfile->global_psymbols,
@@ -3007,7 +3025,7 @@ xcoff_symfile_offsets (struct objfile *objfile, struct section_addr_info *addrs)
 	 sensibly), so just ignore the addr parameter and use 0.
 	 rs6000-nat.c will set the correct section offsets via
 	 objfile_relocate.  */
-	(objfile->section_offsets)->offsets[i] = 0;
+      (objfile->section_offsets)->offsets[i].a = 0;
     }
 }
 
--- a/gdb/xstormy16-tdep.c
+++ b/gdb/xstormy16-tdep.c
@@ -69,7 +69,7 @@ enum gdb_regnum
 };
 
 /* Use an invalid address value as 'not available' marker.  */
-enum { REG_UNAVAIL = (CORE_ADDR) -1 };
+#define REG_UNAVAIL(gdbarch) addr_minus_one (gdbarch)
 
 struct xstormy16_frame_cache
 {
@@ -641,7 +641,7 @@ xstormy16_address_to_pointer (struct gdbarch *gdbarch,
 }
 
 static struct xstormy16_frame_cache *
-xstormy16_alloc_frame_cache (void)
+xstormy16_alloc_frame_cache (struct gdbarch *gdbarch)
 {
   struct xstormy16_frame_cache *cache;
   int i;
@@ -654,7 +654,7 @@ xstormy16_alloc_frame_cache (void)
   cache->uses_fp = 0;
   cache->framesize = 0;
   for (i = 0; i < E_NUM_REGS; ++i)
-    cache->saved_regs[i] = REG_UNAVAIL;
+    cache->saved_regs[i] = REG_UNAVAIL (gdbarch);
 
   return cache;
 }
@@ -670,7 +670,7 @@ xstormy16_frame_cache (struct frame_info *this_frame, void **this_cache)
   if (*this_cache)
     return *this_cache;
 
-  cache = xstormy16_alloc_frame_cache ();
+  cache = xstormy16_alloc_frame_cache (gdbarch);
   *this_cache = cache;
 
   cache->base = get_frame_register_unsigned (this_frame, E_FP_REGNUM);
@@ -689,7 +689,7 @@ xstormy16_frame_cache (struct frame_info *this_frame, void **this_cache)
   cache->saved_sp = cache->base - cache->framesize;
 
   for (i = 0; i < E_NUM_REGS; ++i)
-    if (cache->saved_regs[i] != REG_UNAVAIL)
+    if (cache->saved_regs[i] != REG_UNAVAIL (gdbarch))
       cache->saved_regs[i] += cache->saved_sp;
 
   return cache;
@@ -699,6 +699,7 @@ static struct value *
 xstormy16_frame_prev_register (struct frame_info *this_frame, 
 			       void **this_cache, int regnum)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct xstormy16_frame_cache *cache = xstormy16_frame_cache (this_frame,
                                                                this_cache);
   gdb_assert (regnum >= 0);
@@ -706,7 +707,7 @@ xstormy16_frame_prev_register (struct frame_info *this_frame,
   if (regnum == E_SP_REGNUM && cache->saved_sp)
     return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
 
-  if (regnum < E_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
+  if (regnum < E_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL (gdbarch))
     return frame_unwind_got_memory (this_frame, regnum,
 				    cache->saved_regs[regnum]);
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
  2010-02-17 11:34       ` Jan Kratochvil
@ 2010-02-17 18:50         ` Tom Tromey
  2010-02-20  0:43           ` Jan Kratochvil
  0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2010-02-17 18:50 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Tom> It seems like you could just call the struct CORE_ADDR.

Jan> I thought it would be good to have different type for _address_ vs. for
Jan> _displacement_.  With this difference some math operations are no longer
Jan> valid and I have discovered for example:

Ok, I see.  But in that case wouldn't you still need (or want) to make
CORE_ADDR non-scalar, to avoid hidden errors?

Jan> displacement used as address: invalid but used in
Jan> read_type_unit_scope; it should get some cleanup (not investigated
Jan> more).

Yeah.  There's a comment:

  /* start_symtab needs a low pc, but we don't really have one.
     Do what read_file_scope would do in the absence of such info.  */
  lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));

Tom> Maybe I am being fuzzy today, but I don't follow the logic of this
Tom> statement.  Is this just because we don't expect "too much" overflow?
Tom> Is it impossible for overflow to accumulate in a CORE_ADDR?

Jan> In general "displacement + displacement" operation is invalid and thus it
Jan> cannot overflow.

Thanks.

Tom


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff
  2010-02-17 18:50         ` Tom Tromey
@ 2010-02-20  0:43           ` Jan Kratochvil
  0 siblings, 0 replies; 9+ messages in thread
From: Jan Kratochvil @ 2010-02-20  0:43 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Wed, 17 Feb 2010 19:50:42 +0100, Tom Tromey wrote:
> >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> 
> Tom> It seems like you could just call the struct CORE_ADDR.
> 
> Jan> I thought it would be good to have different type for _address_ vs. for
> Jan> _displacement_.  With this difference some math operations are no longer
> Jan> valid and I have discovered for example:
> 
> Ok, I see.  But in that case wouldn't you still need (or want) to make
> CORE_ADDR non-scalar, to avoid hidden errors?

Yes but that would be even much larger patch than just converting CORE_ADDRs
in use as a displacement into the non-scalar.

It is true this "displacement-only-CORE_ADDRs" has missed some usages of
CORE_ADDR as a displacement.  But it is enough to catch the variable/field
declaration over all the use points of it if it would be left as a scalar.


Thanks,
Jan


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-02-20  0:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-11 11:57 [patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff Jan Kratochvil
2010-02-11 12:13 ` Andreas Schwab
2010-02-11 12:43   ` Jan Kratochvil
     [not found]   ` <20100211124302.GA8435__38068.0548646071$1265892205$gmane$org@host0.dyn.jankratochvil.net>
2010-02-16 23:24     ` Tom Tromey
2010-02-17 11:34       ` Jan Kratochvil
2010-02-17 18:50         ` Tom Tromey
2010-02-20  0:43           ` Jan Kratochvil
2010-02-11 12:51 ` Mark Kettenis
2010-02-11 13:30   ` [cancelled] " Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox