Re: [RFC] DWARF 2 address size != pointer size

Jim Blandy
2006-05-11T22:44:13Z

Fred Fish <fnf@specifix.com> writes:
> For at least one target, MIPS using the o64 ABI with -mlong64, the
> target DWARF2 address size used in the DWARF info (32 bit) is not the
> same as the target pointer size (64 bit). For example, below are some
> fragments from dumping the DWARF info for a simple test case:
>
> Compilation Unit @ 0:
> Length: 175
> Version: 2
> Abbrev Offset: 0
> Pointer Size: 4
> <1><91>: Abbrev Number: 3 (DW_TAG_base_type)
> DW_AT_name : long int
> DW_AT_byte_size : 8
> <1><b0>: Abbrev Number: 4 (DW_TAG_pointer_type)
> DW_AT_byte_size : 8
>
> Note that the header records the address size as 4, which is the
> number of bytes written to the DWARF info when writing addresses, but
> that the target pointer size is 8.
>
> Currently gdb computes the DWARF info address size as:
>
> TARGET_ADDR_BIT / TARGET_CHAR_BIT
>
> Given that the address size is actually recorded in the compilation
> unit header, I believe the best solution would be to use that recorded
> value somehow. I spent a couple days looking for an easy way to tie
> the address size to DWARF expressions that were recorded for later
> evaluation, but didn't come up with anything clean enough to submit.
>
> Another way to divorce the DWARF address size from the TARGET_ADDR_BIT
> is to add another gdbarch paramter, accessed as TARGET_DWARF_ADDR_BIT.
> I've attached a patch that does that. It's simple, but not my first
> choice for solving the problem.
>
> Comments?

Technically, this isn't quite right, since each CU could potentially
have a different address size. It's not a global property of the
debug info.

If I'm understanding the problem, I had a patch for this about a year
ago which I discarded because I found a simpler way to solve the
problem for the port I was working on. But now that other people are
running into it too, I guess I made the wrong choice. I think it's
actually a good idea because it provides more detailed information in
each symbol; I think that could be handy in other ways in the future.

Here's the patch; is it addressing the same thing yours does? I'm not
sure it deals with frame info right, but I'm pretty sure the rest of
it is going in the right direction:

- dwarf2expr.c should definitely get the address size from the context
(this was discussed when dwarf2expr.c was first added, I think).

- dwarf2loc.c should definitely be using psymtab pointers or some sort
of Dwarf CU pointers for SYMBOL_LOCATION_BATON.

2005-04-07 Jim Blandy <jimb@redhat.com>

Include a pointer to the partial symbol table in the symbol
batons, not to the objfile.
* dwarf2loc.h (struct dwarf2_locexpr_baton, struct
dwarf2_loclist_baton): New member 'psymtab', replacing 'objfile'.
* dwarf2loc.c (dwarf2_evaluate_loc_desc): Expect a psymtab, not an
objfile. Store the psymtab's objfile in baton.
(locexpr_read_variable, loclist_read_variable): Pass
baton->psymtab to dwarf2_evaluate_loc_desc, not baton->objfile.
(locexpr_describe_location): Get the file name for thread-local
storage blocks from dlbaton->psymtab->objfile, instead of
dlbaton->objfile.
* dwarf2read.c (struct dwarf2_cu): New member: psymtab.
(dwarf2_build_psymtabs_hard): Zero cu's psymtab pointer.
(psymtab_to_symtab_1): Set cu's psymtab pointer.
(dwarf2_symbol_mark_computed): Store the cu's psymtab in the
batons we create for location expressions and location lists.

Allow dwarf2loc.c to find a compilation unit's address size, given
the psymtab for that compilation unit.
* dwarf2loc.h (dwarf_psymtab_address_size): New function.
* dwarf2read.c (struct dwarf2_pinfo): Add 'address_size' member.
(dwarf2_build_psymtabs_hard): Zero it, since it shouldn't be used yet.
(psymtab_to_symtab_1): Store the cu's address size in it, now that
we're reading full symbols.
(dwarf_psymtab_address_size): New function.

Use the correct address size when parsing Dwarf 2 location lists,
and evaluation DW_OP_deref and DW_OP_deref_size opcodes.
* dwarf2expr.h (struct dwarf_expr_context): New member
'address_size'.
(dwarf2_read_address): Adjust prototype; see next change.
* dwarf2expr.c (dwarf2_read_address): Take the address size as an
argument, rather than returning the address size via a reference
parameter.
(unsigned_address_type, signed_address_type): Take a context as an
argument, and use the address size it specifies.
(execute_stack_op): Pass CTX's address size to dwarf2_read_address.
Use it as the pointer size for DW_OP_deref and DW_OP_deref_size.
Pass CTX to unsigned_address_type and signed_address_type.
* dwarf2loc.h (dwarf_psymtab_address_size): New prototype.
* dwarf2loc.c (find_location_expression): Use baton->psymtab's
address size.
(dwarf2_evaluate_loc_desc): Store PSYMTAB's address size in the
context we're creating.
(dwarf2_loc_desc_needs_frame): Store 1 as the address size in the
context we're creating. Our read_mem just returns zero anyway.
(locexpr_describe_location): Use dlbaton's psymtab's address
size to read DW_OP_GNU_push_tls_address's operand.
* dwarf2-frame.c (size_of_encoded_value): Add forward declaration.
(execute_stack_op, execute_cfa_program): Use
size_of_encoded_value (DW_EH_PE_absptr) as the address size.

Index: gdb/dwarf2-frame.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/dwarf2-frame.c,v
retrieving revision 2.9
diff -c -p -r2.9 dwarf2-frame.c
*** gdb/dwarf2-frame.c 24 Feb 2005 17:03:54 -0000 2.9
--- gdb/dwarf2-frame.c 8 Apr 2005 06:09:21 -0000
*************** dwarf2_frame_state_free (void *p)
*** 202,207 ****
--- 202,209 ----

/* Helper functions for execute_stack_op. */

+ static unsigned int size_of_encoded_value (unsigned char encoding);
+
static CORE_ADDR
read_reg (void *baton, int reg)
{
*************** execute_stack_op (unsigned char *exp, UL
*** 251,256 ****
--- 253,263 ----
ctx->get_frame_base = no_get_frame_base;
ctx->get_tls_address = no_get_tls_address;

+ /* This isn't really right, but the Dwarf spec doesn't say what
+ address size is correct to use for CFI, so this is a reasonable
+ guess. */
+ ctx->address_size = size_of_encoded_value (DW_EH_PE_absptr);
+
dwarf_expr_push (ctx, initial);
dwarf_expr_eval (ctx, exp, len);
result = dwarf_expr_fetch (ctx, 0);
*************** execute_cfa_program (unsigned char *insn
*** 301,307 ****
switch (insn)
{
case DW_CFA_set_loc:
! fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read);
insn_ptr += bytes_read;
break;

--- 308,320 ----
switch (insn)
{
case DW_CFA_set_loc:
! /* This isn't really the right address size to use, but
! the Dwarf spec doesn't say what address size is
! correct to use for CFI, so this is a reasonable
! guess. */
! fs->pc =
! dwarf2_read_address (insn_ptr, insn_end,
! size_of_encoded_value (DW_EH_PE_absptr));
insn_ptr += bytes_read;
break;

Index: gdb/dwarf2expr.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/dwarf2expr.c,v
retrieving revision 2.10
diff -c -p -r2.10 dwarf2expr.c
*** gdb/dwarf2expr.c 4 Apr 2005 20:51:44 -0000 2.10
--- gdb/dwarf2expr.c 8 Apr 2005 06:09:21 -0000
*************** read_sleb128 (unsigned char *buf, unsign
*** 191,221 ****
return buf;
}

! /* Read an address from BUF, and verify that it doesn't extend past
! BUF_END. The address is returned, and *BYTES_READ is set to the
! number of bytes read from BUF. */

CORE_ADDR
! dwarf2_read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read)
{
CORE_ADDR result;

! if (buf_end - buf < TARGET_ADDR_BIT / TARGET_CHAR_BIT)
error ("dwarf2_read_address: Corrupted DWARF expression.");

- *bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
/* NOTE: cagney/2003-05-22: This extract is assuming that a DWARF 2
address is always unsigned. That may or may not be true. */
! result = extract_unsigned_integer (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
return result;
}

/* Return the type of an address, for unsigned arithmetic. */

static struct type *
! unsigned_address_type (void)
{
! switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
{
case 2:
return builtin_type_uint16;
--- 191,221 ----
return buf;
}

! /* Read and return an ADDRESS_SIZE-byte address from BUF, and verify
! that it doesn't extend past BUF_END. */

CORE_ADDR
! dwarf2_read_address (unsigned char *buf,
! unsigned char *buf_end,
! CORE_ADDR address_size)
{
CORE_ADDR result;

! if (buf_end - buf < address_size)
error ("dwarf2_read_address: Corrupted DWARF expression.");

/* NOTE: cagney/2003-05-22: This extract is assuming that a DWARF 2
address is always unsigned. That may or may not be true. */
! result = extract_unsigned_integer (buf, address_size);
return result;
}

/* Return the type of an address, for unsigned arithmetic. */

static struct type *
! unsigned_address_type (struct dwarf_expr_context *ctx)
{
! switch (ctx->address_size)
{
case 2:
return builtin_type_uint16;
*************** unsigned_address_type (void)
*** 232,240 ****
/* Return the type of an address, for signed arithmetic. */

static struct type *
! signed_address_type (void)
{
! switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
{
case 2:
return builtin_type_int16;
--- 232,240 ----
/* Return the type of an address, for signed arithmetic. */

static struct type *
! signed_address_type (struct dwarf_expr_context *ctx)
{
! switch (ctx->address_size)
{
case 2:
return builtin_type_int16;
*************** execute_stack_op (struct dwarf_expr_cont
*** 303,310 ****
break;

case DW_OP_addr:
! result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
! op_ptr += bytes_read;
break;

case DW_OP_const1u:
--- 303,310 ----
break;

case DW_OP_addr:
! result = dwarf2_read_address (op_ptr, op_end, ctx->address_size);
! op_ptr += ctx->address_size;
break;

case DW_OP_const1u:
*************** execute_stack_op (struct dwarf_expr_cont
*** 519,546 ****
{
case DW_OP_deref:
{
! char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
! int bytes_read;

! (ctx->read_mem) (ctx->baton, buf, result,
! TARGET_ADDR_BIT / TARGET_CHAR_BIT);
! result = dwarf2_read_address (buf,
! buf + (TARGET_ADDR_BIT
! / TARGET_CHAR_BIT),
! &bytes_read);
}
break;

case DW_OP_deref_size:
{
! char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
! int bytes_read;

(ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
! result = dwarf2_read_address (buf,
! buf + (TARGET_ADDR_BIT
! / TARGET_CHAR_BIT),
! &bytes_read);
}
break;

--- 519,539 ----
{
case DW_OP_deref:
{
! char *buf = alloca (ctx->address_size);

! (ctx->read_mem) (ctx->baton, buf, result, ctx->address_size);
! result = dwarf2_read_address (buf, buf + ctx->address_size,
! ctx->address_size);
}
break;

case DW_OP_deref_size:
{
! char *buf = alloca (ctx->address_size);

(ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
! result = dwarf2_read_address (buf, buf + ctx->address_size,
! ctx->address_size);
}
break;

*************** execute_stack_op (struct dwarf_expr_cont
*** 591,598 ****
first = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);

! val1 = value_from_longest (unsigned_address_type (), first);
! val2 = value_from_longest (unsigned_address_type (), second);

switch (op)
{
--- 584,591 ----
first = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);

! val1 = value_from_longest (unsigned_address_type (ctx), first);
! val2 = value_from_longest (unsigned_address_type (ctx), second);

switch (op)
{
*************** execute_stack_op (struct dwarf_expr_cont
*** 625,631 ****
break;
case DW_OP_shra:
binop = BINOP_RSH;
! val1 = value_from_longest (signed_address_type (), first);
break;
case DW_OP_xor:
binop = BINOP_BITWISE_XOR;
--- 618,624 ----
break;
case DW_OP_shra:
binop = BINOP_RSH;
! val1 = value_from_longest (signed_address_type (ctx), first);
break;
case DW_OP_xor:
binop = BINOP_BITWISE_XOR;
Index: gdb/dwarf2expr.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/dwarf2expr.h,v
retrieving revision 2.4
diff -c -p -r2.4 dwarf2expr.h
*** gdb/dwarf2expr.h 4 Apr 2005 20:51:44 -0000 2.4
--- gdb/dwarf2expr.h 8 Apr 2005 06:09:21 -0000
*************** struct dwarf_expr_context
*** 32,37 ****
--- 32,42 ----
number of elements allocated to the stack. */
int stack_len, stack_allocated;

+ /* The size of an address, in bytes. For use with operations like
+ DW_OP_addr and DW_OP_deref, and for properly masking arguments to
+ division-like operators. */
+ CORE_ADDR address_size;
+
/* An opaque argument provided by the caller, which will be passed
to all of the callback functions. */
void *baton;
*************** unsigned char *read_uleb128 (unsigned ch
*** 134,139 ****
unsigned char *read_sleb128 (unsigned char *buf, unsigned char *buf_end,
LONGEST * r);
CORE_ADDR dwarf2_read_address (unsigned char *buf, unsigned char *buf_end,
! int *bytes_read);

#endif
--- 139,144 ----
unsigned char *read_sleb128 (unsigned char *buf, unsigned char *buf_end,
LONGEST * r);
CORE_ADDR dwarf2_read_address (unsigned char *buf, unsigned char *buf_end,
! CORE_ADDR addr_size);

#endif
Index: gdb/dwarf2loc.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/dwarf2loc.c,v
retrieving revision 2.9.2.2
diff -c -p -r2.9.2.2 dwarf2loc.c
*** gdb/dwarf2loc.c 8 Apr 2005 04:48:06 -0000 2.9.2.2
--- gdb/dwarf2loc.c 8 Apr 2005 06:09:21 -0000
*************** find_location_expression (struct dwarf2_
*** 56,62 ****
CORE_ADDR base_address = baton->base_address;
CORE_ADDR low, high;
char *loc_ptr, *buf_end;
! unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT, length;
CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));

loc_ptr = baton->data;
--- 56,63 ----
CORE_ADDR base_address = baton->base_address;
CORE_ADDR low, high;
char *loc_ptr, *buf_end;
! unsigned int addr_size = dwarf_psymtab_address_size (baton->psymtab);
! unsigned int length;
CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));

loc_ptr = baton->data;
*************** find_location_expression (struct dwarf2_
*** 64,73 ****

while (1)
{
! low = dwarf2_read_address (loc_ptr, buf_end, &length);
! loc_ptr += length;
! high = dwarf2_read_address (loc_ptr, buf_end, &length);
! loc_ptr += length;

/* An end-of-list entry. */
if (low == 0 && high == 0)
--- 65,74 ----

while (1)
{
! low = dwarf2_read_address (loc_ptr, buf_end, addr_size);
! loc_ptr += addr_size;
! high = dwarf2_read_address (loc_ptr, buf_end, addr_size);
! loc_ptr += addr_size;

/* An end-of-list entry. */
if (low == 0 && high == 0)
*************** dwarf_expr_tls_address (void *baton, COR
*** 196,206 ****

/* Evaluate a location description, starting at DATA and with length
SIZE, to find the current location of variable VAR in the context
! of FRAME. */
static struct value *
dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
unsigned char *data, unsigned short size,
! struct objfile *objfile)
{
struct value *retval;
struct dwarf_expr_baton baton;
--- 197,208 ----

/* Evaluate a location description, starting at DATA and with length
SIZE, to find the current location of variable VAR in the context
! of FRAME. PSYMTAB is the partial symtab for the compilation unit
! defining VAR. */
static struct value *
dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
unsigned char *data, unsigned short size,
! struct partial_symtab *psymtab)
{
struct value *retval;
struct dwarf_expr_baton baton;
*************** dwarf2_evaluate_loc_desc (struct symbol
*** 214,222 ****
}

baton.frame = frame;
! baton.objfile = objfile;

ctx = new_dwarf_expr_context ();
ctx->baton = &baton;
ctx->read_reg = dwarf_expr_read_reg;
ctx->read_mem = dwarf_expr_read_mem;
--- 216,225 ----
}

baton.frame = frame;
! baton.objfile = psymtab->objfile;

ctx = new_dwarf_expr_context ();
+ ctx->address_size = dwarf_psymtab_address_size (psymtab);
ctx->baton = &baton;
ctx->read_reg = dwarf_expr_read_reg;
ctx->read_mem = dwarf_expr_read_mem;
*************** dwarf2_loc_desc_needs_frame (unsigned ch
*** 328,333 ****
--- 331,337 ----
baton.needs_frame = 0;

ctx = new_dwarf_expr_context ();
+ ctx->address_size = 1;
ctx->baton = &baton;
ctx->read_reg = needs_frame_read_reg;
ctx->read_mem = needs_frame_read_mem;
*************** locexpr_read_variable (struct symbol *sy
*** 412,418 ****
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
struct value *val;
val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size,
! dlbaton->objfile);

return val;
}
--- 416,422 ----
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
struct value *val;
val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size,
! dlbaton->psymtab);

return val;
}
*************** locexpr_describe_location (struct symbol
*** 458,471 ****
&& dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
if (dlbaton->data[0] == DW_OP_addr)
{
! int bytes_read;
! CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1],
! &dlbaton->data[dlbaton->size - 1],
! &bytes_read);
fprintf_filtered (stream,
"a thread-local variable at offset %s in the "
"thread-local storage for `%s'",
! paddr_nz (offset), dlbaton->objfile->name);
return 1;
}

--- 462,476 ----
&& dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
if (dlbaton->data[0] == DW_OP_addr)
{
! int address_size = dwarf_psymtab_address_size (dlbaton->psymtab);
! CORE_ADDR offset
! = dwarf2_read_address (&dlbaton->data[1],
! &dlbaton->data[dlbaton->size - 1],
! address_size);
fprintf_filtered (stream,
"a thread-local variable at offset %s in the "
"thread-local storage for `%s'",
! paddr_nz (offset), dlbaton->psymtab->objfile->name);
return 1;
}

*************** loclist_read_variable (struct symbol *sy
*** 521,527 ****
if (data == NULL)
error ("Variable \"%s\" is not available.", SYMBOL_NATURAL_NAME (symbol));

! val = dwarf2_evaluate_loc_desc (symbol, frame, data, size, dlbaton->objfile);

return val;
}
--- 526,533 ----
if (data == NULL)
error ("Variable \"%s\" is not available.", SYMBOL_NATURAL_NAME (symbol));

! val = dwarf2_evaluate_loc_desc (symbol, frame, data, size,
! dlbaton->psymtab);

return val;
}
Index: gdb/dwarf2loc.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/dwarf2loc.h,v
retrieving revision 2.4
diff -c -p -r2.4 dwarf2loc.h
*** gdb/dwarf2loc.h 13 Apr 2004 16:38:54 -0000 2.4
--- gdb/dwarf2loc.h 8 Apr 2005 06:09:21 -0000
*************** struct symbol_ops;
*** 26,31 ****
--- 26,35 ----
/* This header is private to the DWARF-2 reader. It is shared between
dwarf2read.c and dwarf2loc.c. */

+ /* Return the address size given in the compilation unit header for
+ PSYMTAB. */
+ CORE_ADDR dwarf_psymtab_address_size (struct partial_symtab *psymtab);
+
/* The symbol location baton types used by the DWARF-2 reader (i.e.
SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct
dwarf2_locexpr_baton" is for a symbol with a single location
*************** struct dwarf2_locexpr_baton
*** 40,47 ****
/* Length of the location expression. */
unsigned short size;

! /* The objfile containing the symbol whose location we're computing. */
! struct objfile *objfile;
};

struct dwarf2_loclist_baton
--- 44,55 ----
/* Length of the location expression. */
unsigned short size;

! /* The partial symtab structure for the compilation unit containing
! the symbol whose location we're computing. Passing the psymtab
! instead of the objfile gives us access to compilation-unit-
! specific information like Dwarf address size, and the psymtab
! also points to the objfile. */
! struct partial_symtab *psymtab;
};

struct dwarf2_loclist_baton
*************** struct dwarf2_loclist_baton
*** 56,67 ****
/* Length of the location list. */
unsigned short size;

! /* The objfile containing the symbol whose location we're computing. */
! /* Used (only???) by thread local variables. The objfile in which
! this symbol is defined. To find a thread-local variable (e.g., a
! variable declared with the `__thread' storage class), we may need
! to know which object file it's in. */
! struct objfile *objfile;
};

extern const struct symbol_ops dwarf2_locexpr_funcs;
--- 64,76 ----
/* Length of the location list. */
unsigned short size;

!
! /* The partial symtab structure for the compilation unit containing
! the symbol whose location we're computing. Passing the psymtab
! instead of the objfile gives us access to compilation-unit-
! specific information like Dwarf address size, and the psymtab
! also points to the objfile. */
! struct partial_symtab *psymtab;
};

extern const struct symbol_ops dwarf2_locexpr_funcs;
Index: gdb/dwarf2read.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/dwarf2read.c,v
retrieving revision 2.114
diff -c -p -r2.114 dwarf2read.c
*** gdb/dwarf2read.c 23 Jun 2004 23:49:17 -0000 2.114
--- gdb/dwarf2read.c 8 Apr 2005 06:09:22 -0000
*************** struct dwarf2_cu
*** 249,254 ****
--- 249,257 ----
/* The objfile containing this compilation unit. */
struct objfile *objfile;

+ /* The partial symtab for this compilation unit. */
+ struct partial_symtab *psymtab;
+
/* The header of the compilation unit.

FIXME drow/2003-11-10: Some of the things from the comp_unit_head
*************** struct dwarf2_pinfo
*** 471,476 ****
--- 474,483 ----
/* Offset in .debug_info for this compilation unit. */

unsigned long dwarf_info_offset;
+
+ /* Size of addresses in this compilation unit --- from the
+ compilation unit header. */
+ CORE_ADDR address_size;
};

#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
*************** dwarf2_build_psymtabs_hard (struct objfi
*** 1171,1176 ****
--- 1178,1188 ----
beg_of_comp_unit = info_ptr;

cu.objfile = objfile;
+
+ /* We never use the CU's psymtab while building partial symbol
+ tables. */
+ cu.psymtab = NULL;
+
info_ptr = read_comp_unit_head (&cu.header, info_ptr, abfd);

if (cu.header.version != 2)
*************** dwarf2_build_psymtabs_hard (struct objfi
*** 1223,1228 ****
--- 1235,1244 ----
pst->read_symtab_private = (char *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
+ /* This should never be used until we have read in full symbols
+ for PST. */
+ PST_PRIVATE (pst)->address_size = 0;
+
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));

/* Store the function that reads in the rest of the symbol table */
*************** psymtab_to_symtab_1 (struct partial_symt
*** 1935,1944 ****
--- 1951,1964 ----
make_cleanup (really_free_pendings, NULL);

cu.objfile = objfile;
+ cu.psymtab = pst;

/* read in the comp_unit header */
info_ptr = read_comp_unit_head (&cu.header, info_ptr, abfd);

+ /* Save the address size in the psymtab's private data. */
+ PST_PRIVATE (pst)->address_size = cu.header.addr_size;
+
/* Read the abbrevs for this compilation unit */
dwarf2_read_abbrevs (abfd, &cu);
make_cleanup (dwarf2_free_abbrev_table, &cu);
*************** psymtab_to_symtab_1 (struct partial_symt
*** 2000,2005 ****
--- 2020,2031 ----
do_cleanups (back_to);
}

+ CORE_ADDR
+ dwarf_psymtab_address_size (struct partial_symtab *psymtab)
+ {
+ return PST_PRIVATE (psymtab)->address_size;
+ }
+
/* Process a die and its children. */

static void
*************** dwarf2_symbol_mark_computed (struct attr
*** 8126,8132 ****

baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
! baton->objfile = cu->objfile;

/* We don't know how long the location list is, but make sure we
don't run off the edge of the section. */
--- 8152,8158 ----

baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
! baton->psymtab = cu->psymtab;

/* We don't know how long the location list is, but make sure we
don't run off the edge of the section. */
*************** dwarf2_symbol_mark_computed (struct attr
*** 8146,8152 ****

baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_locexpr_baton));
! baton->objfile = cu->objfile;

if (attr_form_is_block (attr))
{
--- 8172,8178 ----

baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_locexpr_baton));
! baton->psymtab = cu->psymtab;

if (attr_form_is_block (attr))
{