This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [rfc] Make DWARF-2 "address size" explicit
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: jimb at codesourcery dot com (Jim Blandy)
- Cc: gdb-patches at sourceware dot org
- Date: Mon, 14 Jan 2008 16:54:46 +0100 (CET)
- Subject: Re: [rfc] Make DWARF-2 "address size" explicit
Hi Jim,
> This is certainly a step in the right direction. However, the proper
> value to use for addr_size is the one that comes from the header of
> the compilation unit containing the expression. (The fact that
> there's no compilation unit associated with the frame information is
> an existing problem.)
>
> I had a patch to carry that through from a long while back. A fellow
> from Intel has been working on updating it; I've encouraged him to
> post it here.
>
> http://sourceware.org/ml/gdb-patches/2006-05/msg00226.html
Thanks for pointing this out! I've updated my patch to retrieve the
address size from the CU header, based on your patch. However, the
implementation details are a bit different (e.g. because there is no
dwarf2_pinfo any more): I use an (opaque) struct dwarf2_cu * in the
location list / location expression batons, and provide a number of
accessor functions to retrieve CU-associated information:
dwarf2_cu_objfile
dwarf2_cu_base_address
dwarf2_cu_addr_size
Apart from that, the behaviour should be identical, with one
exception: what address size to use for CFI. Your patch uses
size_of_encoded_value (DW_EH_PE_absptr)
which basically boils down to:
gdbarch_ptr_bit (current_gdbarch) / TARGET_CHAR_BIT
This would be an effective change in behaviour to what we have
now, which is:
gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT
My patch uses in effect
gdbarch_addr_bit (get_frame_arch (frame)) / TARGET_CHAR_BIT
which does not change behaviour.
However, it might well be that the original code is simply wrong
and we *should* be using ...ptr_bit instead of ...addr_bit.
What do you think?
Tested on i386-linux with no regressions.
Bye,
Ulrich
ChangeLog:
* dwarf2expr.h (struct dwarf_expr_context): Add ADDR_SIZE member.
(dwarf2_read_address): Update prototype.
* dwarf2expr.c (unsigned_address_type): Add ADDR_SIZE parameter.
(signed_address_type): Likewise.
(dwarf2_read_address): Replace BYTES_READ parameter with ADDR_SIZE.
(execute_stack_op): Update calls to unsigned_address_type,
signed_address_type and dwarf2_read_address. Fix implementation
of DW_OP_deref_size.
* dwarf2-frame.c (execute_stack_op): Set ctx->addr_size.
(execute_cfa_program): Update calls to dwarf2_read_address.
* dwarfloc.h (dwarf2_cu_objfile): Add prototype.
(dwarf2_cu_addr_size, dwarf2_cu_base_address): Likewise.
(struct dwarf2_locexpr_baton): Replace OBJFILE with CU.
(struct dwarf2_loclist_baton): Likewise. Remove BASE_ADDRESS.
* dwarf2loc.c (find_location_expression): Update calls to
dwarf2_read_address. Use dwarf2_cu_objfile, dwarf2_cu_addr_size,
and dwarf2_cu_base_address to retrieve CU parameters.
(locexpr_describe_location): Likewise.
(dwarf2_evaluate_loc_desc): Replace OBJFILE with CU parameter.
Set ctx->addr_size to dwarf2_cu_addr_size (cu).
(dwarf2_loc_desc_needs_frame): Add CU parameter. Set ctx->addr_size
to dwarf2_cu_addr_size (cu).
(locexpr_read_variable): Update dwarf2_evaluate_loc_desc call.
(loclist_read_variable): Likewise.
(locexpr_read_needs_frame): Update dwarf2_loc_desc_needs_frame call.
* dwarf2read.c (dwarf2_symbol_mark_computed): Set baton->cu
instead of baton->objfile. Do not set baton->base_address.
(dwarf2_cu_obfile): New function.
(dwarf2_cu_addr_size, dwarf2_cu_base_address): Likewise.
diff -urNp gdb-orig/gdb/dwarf2expr.c gdb-head/gdb/dwarf2expr.c
--- gdb-orig/gdb/dwarf2expr.c 2008-01-14 15:01:05.000000000 +0100
+++ gdb-head/gdb/dwarf2expr.c 2008-01-14 15:15:06.000000000 +0100
@@ -32,7 +32,7 @@
static void execute_stack_op (struct dwarf_expr_context *,
gdb_byte *, gdb_byte *);
-static struct type *unsigned_address_type (void);
+static struct type *unsigned_address_type (int);
/* Create a new context for the expression evaluator. */
@@ -192,20 +192,17 @@ read_sleb128 (gdb_byte *buf, gdb_byte *b
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. */
+/* Read an address of size ADDR_SIZE from BUF, and verify that it
+ doesn't extend past BUF_END. */
CORE_ADDR
-dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int *bytes_read)
+dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int addr_size)
{
CORE_ADDR result;
- if (buf_end - buf < gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT)
+ if (buf_end - buf < addr_size)
error (_("dwarf2_read_address: Corrupted DWARF expression."));
- *bytes_read = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT;
-
/* For most architectures, calling extract_unsigned_integer() alone
is sufficient for extracting an address. However, some
architectures (e.g. MIPS) use signed addresses and using
@@ -229,21 +226,18 @@ dwarf2_read_address (gdb_byte *buf, gdb_
address being returned. */
result = value_as_address (value_from_longest
- (unsigned_address_type (),
- extract_unsigned_integer
- (buf,
- gdbarch_addr_bit (current_gdbarch)
- / TARGET_CHAR_BIT)));
-
+ (unsigned_address_type (addr_size),
+ extract_unsigned_integer (buf, addr_size)));
return result;
}
-/* Return the type of an address, for unsigned arithmetic. */
+/* Return the type of an address of size ADDR_SIZE,
+ for unsigned arithmetic. */
static struct type *
-unsigned_address_type (void)
+unsigned_address_type (int addr_size)
{
- switch (gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT)
+ switch (addr_size)
{
case 2:
return builtin_type_uint16;
@@ -257,12 +251,13 @@ unsigned_address_type (void)
}
}
-/* Return the type of an address, for signed arithmetic. */
+/* Return the type of an address of size ADDR_SIZE,
+ for signed arithmetic. */
static struct type *
-signed_address_type (void)
+signed_address_type (int addr_size)
{
- switch (gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT)
+ switch (addr_size)
{
case 2:
return builtin_type_int16;
@@ -292,7 +287,6 @@ execute_stack_op (struct dwarf_expr_cont
CORE_ADDR result;
ULONGEST uoffset, reg;
LONGEST offset;
- int bytes_read;
switch (op)
{
@@ -332,8 +326,8 @@ execute_stack_op (struct dwarf_expr_cont
break;
case DW_OP_addr:
- result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
- op_ptr += bytes_read;
+ result = dwarf2_read_address (op_ptr, op_end, ctx->addr_size);
+ op_ptr += ctx->addr_size;
break;
case DW_OP_const1u:
@@ -550,34 +544,20 @@ execute_stack_op (struct dwarf_expr_cont
{
case DW_OP_deref:
{
- gdb_byte *buf = alloca (gdbarch_addr_bit (current_gdbarch)
- / TARGET_CHAR_BIT);
- int bytes_read;
-
- (ctx->read_mem) (ctx->baton, buf, result,
- gdbarch_addr_bit (current_gdbarch)
- / TARGET_CHAR_BIT);
- result = dwarf2_read_address (buf,
- buf + (gdbarch_addr_bit
- (current_gdbarch)
- / TARGET_CHAR_BIT),
- &bytes_read);
+ gdb_byte *buf = alloca (ctx->addr_size);
+ (ctx->read_mem) (ctx->baton, buf, result, ctx->addr_size);
+ result = dwarf2_read_address (buf, buf + ctx->addr_size,
+ ctx->addr_size);
}
break;
case DW_OP_deref_size:
{
- gdb_byte *buf
- = alloca (gdbarch_addr_bit (current_gdbarch)
- / TARGET_CHAR_BIT);
- int bytes_read;
-
- (ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
- result = dwarf2_read_address (buf,
- buf + (gdbarch_addr_bit
- (current_gdbarch)
- / TARGET_CHAR_BIT),
- &bytes_read);
+ int addr_size = *op_ptr++;
+ gdb_byte *buf = alloca (addr_size);
+ (ctx->read_mem) (ctx->baton, buf, result, addr_size);
+ result = dwarf2_read_address (buf, buf + addr_size,
+ addr_size);
}
break;
@@ -628,8 +608,10 @@ execute_stack_op (struct dwarf_expr_cont
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);
+ val1 = value_from_longest
+ (unsigned_address_type (ctx->addr_size), first);
+ val2 = value_from_longest
+ (unsigned_address_type (ctx->addr_size), second);
switch (op)
{
@@ -662,7 +644,8 @@ execute_stack_op (struct dwarf_expr_cont
break;
case DW_OP_shra:
binop = BINOP_RSH;
- val1 = value_from_longest (signed_address_type (), first);
+ val1 = value_from_longest
+ (signed_address_type (ctx->addr_size), first);
break;
case DW_OP_xor:
binop = BINOP_BITWISE_XOR;
diff -urNp gdb-orig/gdb/dwarf2expr.h gdb-head/gdb/dwarf2expr.h
--- gdb-orig/gdb/dwarf2expr.h 2008-01-14 15:01:05.000000000 +0100
+++ gdb-head/gdb/dwarf2expr.h 2008-01-14 15:15:06.000000000 +0100
@@ -34,6 +34,9 @@ struct dwarf_expr_context
number of elements allocated to the stack. */
int stack_len, stack_allocated;
+ /* Target address size in bytes. */
+ int addr_size;
+
/* An opaque argument provided by the caller, which will be passed
to all of the callback functions. */
void *baton;
@@ -136,6 +139,6 @@ CORE_ADDR dwarf_expr_fetch (struct dwarf
gdb_byte *read_uleb128 (gdb_byte *buf, gdb_byte *buf_end, ULONGEST * r);
gdb_byte *read_sleb128 (gdb_byte *buf, gdb_byte *buf_end, LONGEST * r);
CORE_ADDR dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end,
- int *bytes_read);
+ int addr_size);
#endif /* dwarf2expr.h */
diff -urNp gdb-orig/gdb/dwarf2-frame.c gdb-head/gdb/dwarf2-frame.c
--- gdb-orig/gdb/dwarf2-frame.c 2008-01-14 15:01:05.000000000 +0100
+++ gdb-head/gdb/dwarf2-frame.c 2008-01-14 15:15:06.000000000 +0100
@@ -302,10 +302,12 @@ static CORE_ADDR
execute_stack_op (gdb_byte *exp, ULONGEST len,
struct frame_info *next_frame, CORE_ADDR initial)
{
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
struct dwarf_expr_context *ctx;
CORE_ADDR result;
ctx = new_dwarf_expr_context ();
+ ctx->addr_size = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT;
ctx->baton = next_frame;
ctx->read_reg = read_reg;
ctx->read_mem = read_mem;
@@ -331,8 +333,8 @@ execute_cfa_program (gdb_byte *insn_ptr,
struct dwarf2_frame_state *fs, int eh_frame_p)
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
- int bytes_read;
struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ int addr_size = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT;
while (insn_ptr < insn_end && fs->pc <= pc)
{
@@ -362,8 +364,8 @@ execute_cfa_program (gdb_byte *insn_ptr,
switch (insn)
{
case DW_CFA_set_loc:
- fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read);
- insn_ptr += bytes_read;
+ fs->pc = dwarf2_read_address (insn_ptr, insn_end, addr_size);
+ insn_ptr += addr_size;
break;
case DW_CFA_advance_loc1:
diff -urNp gdb-orig/gdb/dwarf2loc.c gdb-head/gdb/dwarf2loc.c
--- gdb-orig/gdb/dwarf2loc.c 2008-01-14 15:01:05.000000000 +0100
+++ gdb-head/gdb/dwarf2loc.c 2008-01-14 15:59:19.000000000 +0100
@@ -54,22 +54,23 @@ find_location_expression (struct dwarf2_
CORE_ADDR low, high;
gdb_byte *loc_ptr, *buf_end;
int length;
- unsigned int addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT;
+ struct objfile *objfile = dwarf2_cu_objfile (baton->cu);
+ unsigned int addr_size = dwarf2_cu_addr_size (baton->cu);
CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
/* Adjust base_address for relocatable objects. */
- CORE_ADDR base_offset = ANOFFSET (baton->objfile->section_offsets,
- SECT_OFF_TEXT (baton->objfile));
- CORE_ADDR base_address = baton->base_address + base_offset;
+ CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT (objfile));
+ CORE_ADDR base_address = dwarf2_cu_base_address (baton->cu) + base_offset;
loc_ptr = baton->data;
buf_end = baton->data + baton->size;
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;
+ 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)
@@ -189,7 +190,7 @@ dwarf_expr_tls_address (void *baton, COR
static struct value *
dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
gdb_byte *data, unsigned short size,
- struct objfile *objfile)
+ struct dwarf2_cu *cu)
{
struct gdbarch *arch = get_frame_arch (frame);
struct value *retval;
@@ -205,9 +206,10 @@ dwarf2_evaluate_loc_desc (struct symbol
}
baton.frame = frame;
- baton.objfile = objfile;
+ baton.objfile = dwarf2_cu_objfile (cu);
ctx = new_dwarf_expr_context ();
+ ctx->addr_size = dwarf2_cu_addr_size (cu);
ctx->baton = &baton;
ctx->read_reg = dwarf_expr_read_reg;
ctx->read_mem = dwarf_expr_read_mem;
@@ -318,7 +320,8 @@ needs_frame_tls_address (void *baton, CO
requires a frame to evaluate. */
static int
-dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
+dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+ struct dwarf2_cu *cu)
{
struct needs_frame_baton baton;
struct dwarf_expr_context *ctx;
@@ -327,6 +330,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *d
baton.needs_frame = 0;
ctx = new_dwarf_expr_context ();
+ ctx->addr_size = dwarf2_cu_addr_size (cu);
ctx->baton = &baton;
ctx->read_reg = needs_frame_read_reg;
ctx->read_mem = needs_frame_read_mem;
@@ -429,7 +433,7 @@ locexpr_read_variable (struct symbol *sy
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);
+ dlbaton->cu);
return val;
}
@@ -439,7 +443,8 @@ static int
locexpr_read_needs_frame (struct symbol *symbol)
{
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
- return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size);
+ return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size,
+ dlbaton->cu);
}
/* Print a natural-language description of SYMBOL to STREAM. */
@@ -448,6 +453,7 @@ locexpr_describe_location (struct symbol
{
/* FIXME: be more extensive. */
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+ int addr_size = dwarf2_cu_addr_size (dlbaton->cu);
if (dlbaton->size == 1
&& dlbaton->data[0] >= DW_OP_reg0
@@ -477,14 +483,14 @@ locexpr_describe_location (struct symbol
&& dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
if (dlbaton->data[0] == DW_OP_addr)
{
- int bytes_read;
+ struct objfile *objfile = dwarf2_cu_objfile (dlbaton->cu);
CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1],
&dlbaton->data[dlbaton->size - 1],
- &bytes_read);
+ addr_size);
fprintf_filtered (stream,
"a thread-local variable at offset %s in the "
"thread-local storage for `%s'",
- paddr_nz (offset), dlbaton->objfile->name);
+ paddr_nz (offset), objfile->name);
return 1;
}
@@ -545,8 +551,7 @@ loclist_read_variable (struct symbol *sy
set_value_optimized_out (val, 1);
}
else
- val = dwarf2_evaluate_loc_desc (symbol, frame, data, size,
- dlbaton->objfile);
+ val = dwarf2_evaluate_loc_desc (symbol, frame, data, size, dlbaton->cu);
return val;
}
diff -urNp gdb-orig/gdb/dwarf2loc.h gdb-head/gdb/dwarf2loc.h
--- gdb-orig/gdb/dwarf2loc.h 2008-01-14 15:01:05.000000000 +0100
+++ gdb-head/gdb/dwarf2loc.h 2008-01-14 15:44:51.000000000 +0100
@@ -21,10 +21,21 @@
#define DWARF2LOC_H
struct symbol_ops;
+struct objfile;
+struct dwarf2_cu;
/* This header is private to the DWARF-2 reader. It is shared between
dwarf2read.c and dwarf2loc.c. */
+/* Return the OBJFILE associated with the compilation unit CU. */
+struct objfile *dwarf2_cu_objfile (struct dwarf2_cu *cu);
+
+/* Return the address size given in the compilation unit header for CU. */
+CORE_ADDR dwarf2_cu_addr_size (struct dwarf2_cu *cu);
+
+/* Return the base address given in the compilation unit header for CU. */
+CORE_ADDR dwarf2_cu_base_address (struct dwarf2_cu *cu);
+
/* 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
@@ -39,28 +50,22 @@ struct dwarf2_locexpr_baton
/* Length of the location expression. */
unsigned long size;
- /* The objfile containing the symbol whose location we're computing. */
- struct objfile *objfile;
+ /* The compilation unit containing the symbol whose location
+ we're computing. */
+ struct dwarf2_cu *cu;
};
struct dwarf2_loclist_baton
{
- /* The initial base address for the location list, based on the compilation
- unit. */
- CORE_ADDR base_address;
-
/* Pointer to the start of the location list. */
gdb_byte *data;
/* Length of the location list. */
unsigned long 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;
+ /* The compilation unit containing the symbol whose location
+ we're computing. */
+ struct dwarf2_cu *cu;
};
extern const struct symbol_ops dwarf2_locexpr_funcs;
diff -urNp gdb-orig/gdb/dwarf2read.c gdb-head/gdb/dwarf2read.c
--- gdb-orig/gdb/dwarf2read.c 2008-01-14 15:01:05.000000000 +0100
+++ gdb-head/gdb/dwarf2read.c 2008-01-14 16:07:52.000000000 +0100
@@ -9804,13 +9804,6 @@ static void
dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
- struct objfile *objfile = cu->objfile;
-
- /* Save the master objfile, so that we can report and look up the
- correct file containing this variable. */
- if (objfile->separate_debug_objfile_backlink)
- objfile = objfile->separate_debug_objfile_backlink;
-
if (attr_form_is_section_offset (attr)
/* ".debug_loc" may not exist at all, or the offset may be outside
the section. If so, fall through to the complaint in the
@@ -9821,13 +9814,12 @@ dwarf2_symbol_mark_computed (struct attr
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
- baton->objfile = objfile;
+ baton->cu = cu;
/* We don't know how long the location list is, but make sure we
don't run off the edge of the section. */
baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr);
baton->data = dwarf2_per_objfile->loc_buffer + DW_UNSND (attr);
- baton->base_address = cu->header.base_address;
if (cu->header.base_known == 0)
complaint (&symfile_complaints,
_("Location list used without specifying the CU base address."));
@@ -9841,7 +9833,7 @@ dwarf2_symbol_mark_computed (struct attr
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_locexpr_baton));
- baton->objfile = objfile;
+ baton->cu = cu;
if (attr_form_is_block (attr))
{
@@ -9866,6 +9858,37 @@ dwarf2_symbol_mark_computed (struct attr
}
}
+/* Return the OBJFILE associated with the compilation unit CU. */
+
+struct objfile *
+dwarf2_cu_objfile (struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+
+ /* Return the master objfile, so that we can report and look up the
+ correct file containing this variable. */
+ if (objfile->separate_debug_objfile_backlink)
+ objfile = objfile->separate_debug_objfile_backlink;
+
+ return objfile;
+}
+
+/* Return the address size given in the compilation unit header for CU. */
+
+CORE_ADDR
+dwarf2_cu_addr_size (struct dwarf2_cu *cu)
+{
+ return cu->header.addr_size;
+}
+
+/* Return the base address given in the compilation unit header for CU. */
+
+CORE_ADDR
+dwarf2_cu_base_address (struct dwarf2_cu *cu)
+{
+ return cu->header.base_address;
+}
+
/* Locate the compilation unit from CU's objfile which contains the
DIE at OFFSET. Raises an error on failure. */
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com