summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Ludvig <mludvig@suse.cz>2002-07-03 06:00:29 +0000
committerMichal Ludvig <mludvig@suse.cz>2002-07-03 06:00:29 +0000
commit252b2a3e60db3a7de2daf001edb011466717a7c4 (patch)
tree09dfa7ae3cb899b69b2a4f66fd9f7d6ba2b31ad9
parente4681ddb79064f6465f5ee6f36218db73f5da736 (diff)
downloadbinutils-gdb-252b2a3e60db3a7de2daf001edb011466717a7c4.tar.gz
Merge with mainline.
-rw-r--r--gdb/ChangeLog45
-rw-r--r--gdb/dwarf2cfi.c499
-rw-r--r--gdb/testsuite/ChangeLog8
-rw-r--r--gdb/testsuite/gdb.asm/asm-source.exp4
-rw-r--r--gdb/x86-64-linux-nat.c78
-rw-r--r--gdb/x86-64-tdep.c221
-rw-r--r--gdb/x86-64-tdep.h4
7 files changed, 601 insertions, 258 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a91540f3440..d5294f3a611 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,48 @@
+2002-07-03 Michal Ludvig <mludvig@suse.cz>
+
+ Merge from mainline:
+
+ 2002-06-21 Michal Ludvig <mludvig@suse.cz>
+ * dwarf2cfi.c (read_encoded_pointer): Don't handle pointer
+ encoding anymore.
+ (pointer_encoding, enum ptr_encoding): New.
+ (execute_cfa_program): Take care about pointer encoding.
+ (dwarf2_build_frame_info): Only call parse_frame_info for
+ .debug_frame and .eh_frame.
+ (parse_frame_info): New, derived from former dwarf2_build_frame_info.
+ fixed augmentation handling, added relative addressing,
+ ignore duplicate FDEs. Added comments.
+ * dwarf2cfi.c: Reindented.
+
+ 2002-06-20 Michal Ludvig <mludvig@suse.cz>
+ * x86-64-tdep.c (x86_64_register_nr2name): Rename to
+ x86_64_register_name. Return type changed to 'const char *'.
+ (x86_64_register_name2nr): Rename to x86_64_register_number.
+ (x86_64_gdbarch_init): Update to reflect the change.
+ * x86-64-tdep.h: Ditto.
+ * x86-64-linux-nat.c (x86_64_fxsave_offset)
+ (supply_fpregset): Ditto.
+
+ 2002-06-11 Michal Ludvig <mludvig@suse.cz>
+ * dwarf2cfi.c (unwind_tmp_obstack_init): New.
+ (unwind_tmp_obstack_free, parse_frame_info)
+ (update_context, cfi_read_fp, cfi_write_fp)
+ (cfi_frame_chain, cfi_init_extra_frame_info)
+ (cfi_virtual_frame_pointer): Use the above function.
+ * x86-64-tdep.c (x86_64_skip_prologue): Fix to work on functions
+ without debug information too.
+
+ 2002-06-07 Michal Ludvig <mludvig@suse.cz>
+ * x86-64-linux-nat.c (x86_64_fxsave_offset): New.
+ (supply_fpregset, fill_fpregset): Don't call i387_*_fxsave,
+ better do the things actually here.
+ * x86-64-tdep.c (x86_64_register_name2nr): New.
+ (x86_64_register_name): Renamed to x86_64_register_nr2name.
+ (x86_64_gdbarch_init): Respect the above change.
+ * x86-64-tdep.h (x86_64_register_name2nr)
+ (x86_64_register_nr2name): Add prototypes.
+ * config/i386/x86-64linux.mt (TDEPFILES): Remove i387-tdep.o.
+
2002-06-28 Andrew Cagney <ac131313@redhat.com>
* Makefile.in (objfiles_h): Add $(bcache_h).
diff --git a/gdb/dwarf2cfi.c b/gdb/dwarf2cfi.c
index 783d1c014e0..442ae70e540 100644
--- a/gdb/dwarf2cfi.c
+++ b/gdb/dwarf2cfi.c
@@ -34,7 +34,7 @@
Frame Descriptors. */
struct cie_unit
{
- /* Offset of this unit in dwarf_frame_buffer. */
+ /* Offset of this unit in .debug_frame or .eh_frame. */
ULONGEST offset;
/* A null-terminated string that identifies the augmentation to this CIE or
@@ -176,6 +176,15 @@ struct frame_state
struct objfile *objfile;
};
+enum ptr_encoding
+{
+ PE_absptr = DW_EH_PE_absptr,
+ PE_pcrel = DW_EH_PE_pcrel,
+ PE_textrel = DW_EH_PE_textrel,
+ PE_datarel = DW_EH_PE_datarel,
+ PE_funcrel = DW_EH_PE_funcrel
+};
+
#define UNWIND_CONTEXT(fi) ((struct context *) (fi->context))
@@ -188,8 +197,6 @@ extern file_ptr dwarf_frame_offset;
extern unsigned int dwarf_frame_size;
extern file_ptr dwarf_eh_frame_offset;
extern unsigned int dwarf_eh_frame_size;
-
-static char *dwarf_frame_buffer;
extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset,
@@ -201,26 +208,28 @@ static void fde_chunks_need_space ();
static struct context *context_alloc ();
static struct frame_state *frame_state_alloc ();
+static void unwind_tmp_obstack_init ();
static void unwind_tmp_obstack_free ();
static void context_cpy (struct context *dst, struct context *src);
-static unsigned int read_1u (bfd *abfd, char **p);
-static int read_1s (bfd *abfd, char **p);
-static unsigned int read_2u (bfd *abfd, char **p);
-static int read_2s (bfd *abfd, char **p);
-static unsigned int read_4u (bfd *abfd, char **p);
-static int read_4s (bfd *abfd, char **p);
-static ULONGEST read_8u (bfd *abfd, char **p);
-static LONGEST read_8s (bfd *abfd, char **p);
-
-static ULONGEST read_uleb128 (bfd *abfd, char **p);
-static LONGEST read_sleb128 (bfd *abfd, char **p);
-static CORE_ADDR read_pointer (bfd *abfd, char **p);
-static CORE_ADDR read_encoded_pointer (bfd *abfd, char **p,
+static unsigned int read_1u (bfd * abfd, char **p);
+static int read_1s (bfd * abfd, char **p);
+static unsigned int read_2u (bfd * abfd, char **p);
+static int read_2s (bfd * abfd, char **p);
+static unsigned int read_4u (bfd * abfd, char **p);
+static int read_4s (bfd * abfd, char **p);
+static ULONGEST read_8u (bfd * abfd, char **p);
+static LONGEST read_8s (bfd * abfd, char **p);
+
+static ULONGEST read_uleb128 (bfd * abfd, char **p);
+static LONGEST read_sleb128 (bfd * abfd, char **p);
+static CORE_ADDR read_pointer (bfd * abfd, char **p);
+static CORE_ADDR read_encoded_pointer (bfd * abfd, char **p,
unsigned char encoding);
+static enum ptr_encoding pointer_encoding (unsigned char encoding);
-static LONGEST read_initial_length (bfd *abfd, char *buf, int *bytes_read);
-static ULONGEST read_length (bfd *abfd, char *buf, int *bytes_read,
+static LONGEST read_initial_length (bfd * abfd, char *buf, int *bytes_read);
+static ULONGEST read_length (bfd * abfd, char *buf, int *bytes_read,
int dwarf64);
static int is_cie (ULONGEST cie_id, int dwarf64);
@@ -235,11 +244,12 @@ static void frame_state_for (struct context *context, struct frame_state *fs);
static void get_reg (char *reg, struct context *context, int regnum);
static CORE_ADDR execute_stack_op (struct objfile *objfile,
char *op_ptr, char *op_end,
- struct context *context, CORE_ADDR initial);
+ struct context *context,
+ CORE_ADDR initial);
static void update_context (struct context *context, struct frame_state *fs,
int chain);
-
+
/* Memory allocation functions. */
static struct fde_unit *
fde_unit_alloc (void)
@@ -301,17 +311,23 @@ frame_state_alloc ()
fs = (struct frame_state *) obstack_alloc (&unwind_tmp_obstack,
sizeof (struct frame_state));
memset (fs, 0, sizeof (struct frame_state));
- fs->regs.reg = (struct frame_state_reg *) obstack_alloc (&unwind_tmp_obstack,
- regs_size);
+ fs->regs.reg =
+ (struct frame_state_reg *) obstack_alloc (&unwind_tmp_obstack, regs_size);
memset (fs->regs.reg, 0, regs_size);
return fs;
}
static void
+unwind_tmp_obstack_init ()
+{
+ obstack_init (&unwind_tmp_obstack);
+}
+
+static void
unwind_tmp_obstack_free ()
{
obstack_free (&unwind_tmp_obstack, NULL);
- obstack_init (&unwind_tmp_obstack);
+ unwind_tmp_obstack_init ();
}
static void
@@ -334,92 +350,92 @@ context_cpy (struct context *dst, struct context *src)
dreg = dst->reg;
*dst = *src;
dst->reg = dreg;
-
+
memcpy (dst->reg, src->reg, regs_size);
}
static unsigned int
-read_1u (bfd *abfd, char **p)
+read_1u (bfd * abfd, char **p)
{
unsigned ret;
- ret= bfd_get_8 (abfd, (bfd_byte *) *p);
- (*p) ++;
+ ret = bfd_get_8 (abfd, (bfd_byte *) * p);
+ (*p)++;
return ret;
}
static int
-read_1s (bfd *abfd, char **p)
+read_1s (bfd * abfd, char **p)
{
int ret;
- ret= bfd_get_signed_8 (abfd, (bfd_byte *) *p);
- (*p) ++;
+ ret = bfd_get_signed_8 (abfd, (bfd_byte *) * p);
+ (*p)++;
return ret;
}
static unsigned int
-read_2u (bfd *abfd, char **p)
+read_2u (bfd * abfd, char **p)
{
unsigned ret;
- ret= bfd_get_16 (abfd, (bfd_byte *) *p);
- (*p) ++;
+ ret = bfd_get_16 (abfd, (bfd_byte *) * p);
+ (*p)++;
return ret;
}
static int
-read_2s (bfd *abfd, char **p)
+read_2s (bfd * abfd, char **p)
{
int ret;
- ret= bfd_get_signed_16 (abfd, (bfd_byte *) *p);
+ ret = bfd_get_signed_16 (abfd, (bfd_byte *) * p);
(*p) += 2;
return ret;
}
static unsigned int
-read_4u (bfd *abfd, char **p)
+read_4u (bfd * abfd, char **p)
{
unsigned int ret;
- ret= bfd_get_32 (abfd, (bfd_byte *) *p);
+ ret = bfd_get_32 (abfd, (bfd_byte *) * p);
(*p) += 4;
return ret;
}
static int
-read_4s (bfd *abfd, char **p)
+read_4s (bfd * abfd, char **p)
{
int ret;
- ret= bfd_get_signed_32 (abfd, (bfd_byte *) *p);
+ ret = bfd_get_signed_32 (abfd, (bfd_byte *) * p);
(*p) += 4;
return ret;
}
static ULONGEST
-read_8u (bfd *abfd, char **p)
+read_8u (bfd * abfd, char **p)
{
ULONGEST ret;
- ret = bfd_get_64 (abfd, (bfd_byte *) *p);
+ ret = bfd_get_64 (abfd, (bfd_byte *) * p);
(*p) += 8;
return ret;
}
static LONGEST
-read_8s (bfd *abfd, char **p)
+read_8s (bfd * abfd, char **p)
{
LONGEST ret;
- ret = bfd_get_signed_64 (abfd, (bfd_byte *) *p);
+ ret = bfd_get_signed_64 (abfd, (bfd_byte *) * p);
(*p) += 8;
return ret;
}
static ULONGEST
-read_uleb128 (bfd *abfd, char **p)
+read_uleb128 (bfd * abfd, char **p)
{
ULONGEST ret;
int i, shift;
@@ -430,8 +446,8 @@ read_uleb128 (bfd *abfd, char **p)
i = 0;
while (1)
{
- byte = bfd_get_8 (abfd, (bfd_byte *) *p);
- (*p) ++;
+ byte = bfd_get_8 (abfd, (bfd_byte *) * p);
+ (*p)++;
ret |= ((unsigned long) (byte & 127) << shift);
if ((byte & 128) == 0)
{
@@ -443,7 +459,7 @@ read_uleb128 (bfd *abfd, char **p)
}
static LONGEST
-read_sleb128 (bfd *abfd, char **p)
+read_sleb128 (bfd * abfd, char **p)
{
LONGEST ret;
int i, shift, size, num_read;
@@ -456,8 +472,8 @@ read_sleb128 (bfd *abfd, char **p)
i = 0;
while (1)
{
- byte = bfd_get_8 (abfd, (bfd_byte *) *p);
- (*p) ++;
+ byte = bfd_get_8 (abfd, (bfd_byte *) * p);
+ (*p)++;
ret |= ((long) (byte & 127) << shift);
shift += 7;
if ((byte & 128) == 0)
@@ -473,7 +489,7 @@ read_sleb128 (bfd *abfd, char **p)
}
static CORE_ADDR
-read_pointer (bfd *abfd, char **p)
+read_pointer (bfd * abfd, char **p)
{
switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
{
@@ -486,8 +502,11 @@ read_pointer (bfd *abfd, char **p)
}
}
+/* This functions only reads appropriate amount of data from *p
+ * and returns the resulting value. Calling function must handle
+ * different encoding possibilities itself! */
static CORE_ADDR
-read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding)
+read_encoded_pointer (bfd * abfd, char **p, unsigned char encoding)
{
CORE_ADDR ret;
@@ -529,22 +548,33 @@ read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding)
"read_encoded_pointer: unknown pointer encoding");
}
- if (ret != 0)
- switch (encoding & 0xf0)
- {
- case DW_EH_PE_absptr:
- break;
- case DW_EH_PE_pcrel:
- ret += (CORE_ADDR) *p;
- break;
- case DW_EH_PE_textrel:
- case DW_EH_PE_datarel:
- case DW_EH_PE_funcrel:
- default:
- internal_error (__FILE__, __LINE__,
- "read_encoded_pointer: unknown pointer encoding");
- }
+ return ret;
+}
+
+/* Variable 'encoding' carries 3 different flags:
+ * - encoding & 0x0f : size of the address (handled in read_encoded_pointer())
+ * - encoding & 0x70 : type (absolute, relative, ...)
+ * - encoding & 0x80 : indirect flag (DW_EH_PE_indirect == 0x80). */
+enum ptr_encoding
+pointer_encoding (unsigned char encoding)
+{
+ int ret;
+
+ if (encoding & DW_EH_PE_indirect)
+ warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect");
+ switch (encoding & 0x70)
+ {
+ case DW_EH_PE_absptr:
+ case DW_EH_PE_pcrel:
+ case DW_EH_PE_textrel:
+ case DW_EH_PE_datarel:
+ case DW_EH_PE_funcrel:
+ ret = encoding & 0x70;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "CFI: unknown pointer encoding");
+ }
return ret;
}
@@ -584,8 +614,8 @@ read_length (bfd * abfd, char *buf, int *bytes_read, int dwarf64)
}
static void
-execute_cfa_program ( struct objfile *objfile, char *insn_ptr, char *insn_end,
- struct context *context, struct frame_state *fs)
+execute_cfa_program (struct objfile *objfile, char *insn_ptr, char *insn_end,
+ struct context *context, struct frame_state *fs)
{
struct frame_state_regs *unused_rs = NULL;
@@ -604,7 +634,7 @@ execute_cfa_program ( struct objfile *objfile, char *insn_ptr, char *insn_end,
{
reg = insn & 0x3f;
uoffset = read_uleb128 (objfile->obfd, &insn_ptr);
- offset = (long) uoffset * fs->data_align;
+ offset = (long) uoffset *fs->data_align;
fs->regs.reg[reg].how = REG_SAVED_OFFSET;
fs->regs.reg[reg].loc.offset = offset;
}
@@ -619,6 +649,10 @@ execute_cfa_program ( struct objfile *objfile, char *insn_ptr, char *insn_end,
case DW_CFA_set_loc:
fs->pc = read_encoded_pointer (objfile->obfd, &insn_ptr,
fs->addr_encoding);
+
+ if (pointer_encoding (fs->addr_encoding) != PE_absptr)
+ warning ("CFI: DW_CFA_set_loc uses relative addressing");
+
break;
case DW_CFA_advance_loc1:
@@ -806,13 +840,13 @@ frame_state_for (struct context *context, struct frame_state *fs)
if (fde == NULL)
return;
-
+
fs->pc = fde->initial_location;
if (fde->cie_ptr)
- {
+ {
cie = fde->cie_ptr;
-
+
fs->code_align = cie->code_align;
fs->data_align = cie->data_align;
fs->retaddr_column = cie->ra;
@@ -823,11 +857,10 @@ frame_state_for (struct context *context, struct frame_state *fs)
cie->data + cie->data_length, context, fs);
execute_cfa_program (cie->objfile, fde->data,
fde->data + fde->data_length, context, fs);
- }
+ }
else
- internal_error (__FILE__, __LINE__,
- "%s(): Internal error: fde->cie_ptr==NULL !",
- __func__);
+ internal_error (__FILE__, __LINE__,
+ "%s(): Internal error: fde->cie_ptr==NULL !", __func__);
}
static void
@@ -854,8 +887,7 @@ get_reg (char *reg, struct context *context, int regnum)
REGISTER_RAW_SIZE (regnum));
break;
default:
- internal_error (__FILE__, __LINE__,
- "get_reg: unknown register rule");
+ internal_error (__FILE__, __LINE__, "get_reg: unknown register rule");
}
}
@@ -1208,8 +1240,8 @@ execute_stack_op (struct objfile *objfile,
case DW_OP_ne:
result = (LONGEST) first != (LONGEST) second;
break;
- default: /* This label is here just to avoid warning. */
- break;
+ default: /* This label is here just to avoid warning. */
+ break;
}
}
break;
@@ -1255,8 +1287,11 @@ update_context (struct context *context, struct frame_state *fs, int chain)
CORE_ADDR cfa;
long i;
+ unwind_tmp_obstack_init ();
+
orig_context = context_alloc ();
context_cpy (orig_context, context);
+
/* Compute this frame's CFA. */
switch (fs->cfa_how)
{
@@ -1267,9 +1302,9 @@ update_context (struct context *context, struct frame_state *fs, int chain)
case CFA_EXP:
/* ??? No way of knowing what register number is the stack pointer
- to do the same sort of handling as above. Assume that if the
- CFA calculation is so complicated as to require a stack program
- that this will not be a problem. */
+ to do the same sort of handling as above. Assume that if the
+ CFA calculation is so complicated as to require a stack program
+ that this will not be a problem. */
{
char *exp = fs->cfa_exp;
ULONGEST len;
@@ -1371,39 +1406,46 @@ compare_fde_unit (const void *a, const void *b)
}
/* Build the cie_chunks and fde_chunks tables from informations
- in .debug_frame section. */
-void
-dwarf2_build_frame_info (struct objfile *objfile)
+ found in .debug_frame and .eh_frame sections. */
+/* We can handle both of these sections almost in the same way, however there
+ are some exceptions:
+ - CIE ID is -1 in debug_frame, but 0 in eh_frame
+ - eh_frame may contain some more information that are used only by gcc
+ (eg. personality pointer, LSDA pointer, ...). Most of them we can ignore.
+ - In debug_frame FDE's item cie_id contains offset of it's parent CIE.
+ In eh_frame FDE's item cie_id is a relative pointer to the parent CIE.
+ Anyway we don't need to bother with this, because we are smart enough
+ to keep the pointer to the parent CIE of oncomming FDEs in 'last_cie'.
+ - Although debug_frame items can contain Augmentation as well as
+ eh_frame ones, I have never seen them non-empty. Thus only in eh_frame
+ we can encounter for example non-absolute pointers (Aug. 'R').
+ -- mludvig */
+static void
+parse_frame_info (struct objfile *objfile, file_ptr frame_offset,
+ unsigned int frame_size, int eh_frame)
{
bfd *abfd = objfile->obfd;
+ asection *curr_section_ptr;
char *start = NULL;
char *end = NULL;
- int from_eh = 0;
-
- obstack_init (&unwind_tmp_obstack);
-
- dwarf_frame_buffer = 0;
+ char *frame_buffer = NULL;
+ char *curr_section_name, *aug_data;
+ struct cie_unit *last_cie = NULL;
+ int last_dup_fde = 0;
+ int aug_len, i;
+ CORE_ADDR curr_section_vma = 0;
- if (dwarf_frame_offset)
- {
- dwarf_frame_buffer = dwarf2_read_section (objfile,
- dwarf_frame_offset,
- dwarf_frame_size);
+ unwind_tmp_obstack_init ();
- start = dwarf_frame_buffer;
- end = dwarf_frame_buffer + dwarf_frame_size;
- }
- else if (dwarf_eh_frame_offset)
- {
- dwarf_frame_buffer = dwarf2_read_section (objfile,
- dwarf_eh_frame_offset,
- dwarf_eh_frame_size);
+ frame_buffer = dwarf2_read_section (objfile, frame_offset, frame_size);
- start = dwarf_frame_buffer;
- end = dwarf_frame_buffer + dwarf_eh_frame_size;
+ start = frame_buffer;
+ end = frame_buffer + frame_size;
- from_eh = 1;
- }
+ curr_section_name = eh_frame ? ".eh_frame" : ".debug_frame";
+ curr_section_ptr = bfd_get_section_by_name (abfd, curr_section_name);
+ if (curr_section_ptr)
+ curr_section_vma = curr_section_ptr->vma;
if (start)
{
@@ -1411,9 +1453,8 @@ dwarf2_build_frame_info (struct objfile *objfile)
{
unsigned long length;
ULONGEST cie_id;
- ULONGEST unit_offset = start - dwarf_frame_buffer;
- int bytes_read;
- int dwarf64;
+ ULONGEST unit_offset = start - frame_buffer;
+ int bytes_read, dwarf64;
char *block_end;
length = read_initial_length (abfd, start, &bytes_read);
@@ -1421,10 +1462,16 @@ dwarf2_build_frame_info (struct objfile *objfile)
dwarf64 = (bytes_read == 12);
block_end = start + length;
+ if (length == 0)
+ {
+ start = block_end;
+ continue;
+ }
+
cie_id = read_length (abfd, start, &bytes_read, dwarf64);
start += bytes_read;
- if ((from_eh && cie_id == 0) || is_cie (cie_id, dwarf64))
+ if ((eh_frame && cie_id == 0) || is_cie (cie_id, dwarf64))
{
struct cie_unit *cie = cie_unit_alloc ();
char *aug;
@@ -1440,84 +1487,186 @@ dwarf2_build_frame_info (struct objfile *objfile)
start++; /* version */
cie->augmentation = aug = start;
- while (*start)
- start++;
- start++; /* skip past NUL */
+ while (*start++); /* Skips last NULL as well */
cie->code_align = read_uleb128 (abfd, &start);
cie->data_align = read_sleb128 (abfd, &start);
cie->ra = read_1u (abfd, &start);
+ /* Augmentation:
+ z Indicates that a uleb128 is present to size the
+ augmentation section.
+ L Indicates the encoding (and thus presence) of
+ an LSDA pointer in the FDE augmentation.
+ R Indicates a non-default pointer encoding for
+ FDE code pointers.
+ P Indicates the presence of an encoding + language
+ personality routine in the CIE augmentation.
+
+ [This info comes from GCC's dwarf2out.c]
+ */
if (*aug == 'z')
{
- int xtra = read_uleb128 (abfd, &start);
- start += xtra;
+ aug_len = read_uleb128 (abfd, &start);
+ aug_data = start;
+ start += aug_len;
++aug;
}
+ cie->data = start;
+ cie->data_length = block_end - cie->data;
+
while (*aug != '\0')
{
if (aug[0] == 'e' && aug[1] == 'h')
{
- start += sizeof (void *);
- aug += 2;
+ aug_data += sizeof (void *);
+ aug++;
}
else if (aug[0] == 'R')
+ cie->addr_encoding = *aug_data++;
+ else if (aug[0] == 'P')
{
- cie->addr_encoding = *start++;
- aug += 1;
+ CORE_ADDR pers_addr;
+ int pers_addr_enc;
+
+ pers_addr_enc = *aug_data++;
+ /* We don't need pers_addr value and so we
+ don't care about it's encoding. */
+ pers_addr = read_encoded_pointer (abfd, &aug_data,
+ pers_addr_enc);
}
- else if (aug[0] == 'P')
+ else if (aug[0] == 'L' && eh_frame)
{
- CORE_ADDR ptr;
- ptr = read_encoded_pointer (abfd, &start,
- cie->addr_encoding);
- aug += 1;
+ int lsda_addr_enc;
+
+ /* Perhaps we should save this to CIE for later use?
+ Do we need it for something in GDB? */
+ lsda_addr_enc = *aug_data++;
}
else
- warning ("%s(): unknown augmentation", __func__);
+ warning ("CFI warning: unknown augmentation \"%c\""
+ " in \"%s\" of\n"
+ "\t%s", aug[0], curr_section_name,
+ objfile->name);
+ aug++;
}
- cie->data = start;
- cie->data_length = block_end - start;
+ last_cie = cie;
}
else
{
struct fde_unit *fde;
struct cie_unit *cie;
+ int dup = 0;
+ CORE_ADDR init_loc;
+
+ /* We assume that debug_frame is in order
+ CIE,FDE,CIE,FDE,FDE,... and thus the CIE for this FDE
+ should be stored in last_cie pointer. If not, we'll
+ try to find it by the older way. */
+ if (last_cie)
+ cie = last_cie;
+ else
+ {
+ warning ("CFI: last_cie == NULL. "
+ "Perhaps a malformed %s section in '%s'...?\n",
+ curr_section_name, objfile->name);
- fde_chunks_need_space ();
- fde = fde_unit_alloc ();
+ cie = cie_chunks;
+ while (cie)
+ {
+ if (cie->objfile == objfile)
+ {
+ if (eh_frame &&
+ (cie->offset ==
+ (unit_offset + bytes_read - cie_id)))
+ break;
+ if (!eh_frame && (cie->offset == cie_id))
+ break;
+ }
+
+ cie = cie->next;
+ }
+ if (!cie)
+ error ("CFI: can't find CIE pointer");
+ }
- fde_chunks.array[fde_chunks.elems++] = fde;
-
- fde->initial_location = read_pointer (abfd, &start)
- + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- fde->address_range = read_pointer (abfd, &start);
+ init_loc = read_encoded_pointer (abfd, &start,
+ cie->addr_encoding);
- cie = cie_chunks;
- while(cie)
- {
- if (cie->objfile == objfile)
+ switch (pointer_encoding (cie->addr_encoding))
{
- if (from_eh && (cie->offset == (unit_offset + bytes_read - cie_id)))
- break;
- if (!from_eh && (cie->offset == cie_id))
- break;
+ case PE_absptr:
+ break;
+ case PE_pcrel:
+ /* start-frame_buffer gives offset from
+ the beginning of actual section. */
+ init_loc += curr_section_vma + start - frame_buffer;
+ break;
+ default:
+ warning ("CFI: Unsupported pointer encoding\n");
}
- cie = cie->next;
- }
-
- if (!cie)
- error ("%s(): can't find CIE pointer", __func__);
- fde->cie_ptr = cie;
+ /* For relocatable objects we must add an offset telling
+ where the section is actually mapped in the memory. */
+ init_loc += ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT (objfile));
+
+ /* If we have both .debug_frame and .eh_frame present in
+ a file, we must eliminate duplicate FDEs. For now we'll
+ run through all entries in fde_chunks and check it one
+ by one. Perhaps in the future we can implement a faster
+ searching algorithm. */
+ /* eh_frame==2 indicates, that this file has an already
+ parsed .debug_frame too. When eh_frame==1 it means, that no
+ .debug_frame is present and thus we don't need to check for
+ duplicities. eh_frame==0 means, that we parse .debug_frame
+ and don't need to care about duplicate FDEs, because
+ .debug_frame is parsed first. */
+ if (eh_frame == 2)
+ for (i = 0; eh_frame == 2 && i < fde_chunks.elems; i++)
+ {
+ /* We assume that FDEs in .debug_frame and .eh_frame
+ have the same order (if they are present, of course).
+ If we find a duplicate entry for one FDE and save
+ it's index to last_dup_fde it's very likely, that
+ we'll find an entry for the following FDE right after
+ the previous one. Thus in many cases we'll run this
+ loop only once. */
+ last_dup_fde = (last_dup_fde + i) % fde_chunks.elems;
+ if (fde_chunks.array[last_dup_fde]->initial_location
+ == init_loc)
+ {
+ dup = 1;
+ break;
+ }
+ }
+
+ /* Allocate a new entry only if this FDE isn't a duplicate of
+ something we have already seen. */
+ if (!dup)
+ {
+ fde_chunks_need_space ();
+ fde = fde_unit_alloc ();
- if (cie->augmentation[0] == 'z')
- read_uleb128 (abfd, &start);
+ fde_chunks.array[fde_chunks.elems++] = fde;
- fde->data = start;
- fde->data_length = block_end - start;
+ fde->initial_location = init_loc;
+ fde->address_range = read_encoded_pointer (abfd, &start,
+ cie->
+ addr_encoding);
+
+ fde->cie_ptr = cie;
+
+ /* Here we intentionally ignore augmentation data
+ from FDE, because we don't need them. */
+ if (cie->augmentation[0] == 'z')
+ start += read_uleb128 (abfd, &start);
+
+ fde->data = start;
+ fde->data_length = block_end - start;
+ }
}
start = block_end;
}
@@ -1525,7 +1674,30 @@ dwarf2_build_frame_info (struct objfile *objfile)
sizeof (struct fde_unit *), compare_fde_unit);
}
}
-
+
+/* We must parse both .debug_frame section and .eh_frame because
+ * not all frames must be present in both of these sections. */
+void
+dwarf2_build_frame_info (struct objfile *objfile)
+{
+ int after_debug_frame = 0;
+
+ /* If we have .debug_frame then the parser is called with
+ eh_frame==0 for .debug_frame and eh_frame==2 for .eh_frame,
+ otherwise it's only called once for .eh_frame with argument
+ eh_frame==1. */
+
+ if (dwarf_frame_offset)
+ {
+ parse_frame_info (objfile, dwarf_frame_offset,
+ dwarf_frame_size, 0 /* = debug_frame */ );
+ after_debug_frame = 1;
+ }
+
+ if (dwarf_eh_frame_offset)
+ parse_frame_info (objfile, dwarf_eh_frame_offset, dwarf_eh_frame_size,
+ 1 /* = eh_frame */ + after_debug_frame);
+}
/* Return the frame address. */
CORE_ADDR
@@ -1535,6 +1707,8 @@ cfi_read_fp ()
struct frame_state *fs;
CORE_ADDR cfa;
+ unwind_tmp_obstack_init ();
+
context = context_alloc ();
fs = frame_state_alloc ();
@@ -1544,7 +1718,9 @@ cfi_read_fp ()
update_context (context, fs, 0);
cfa = context->cfa;
+
unwind_tmp_obstack_free ();
+
return cfa;
}
@@ -1556,6 +1732,8 @@ cfi_write_fp (CORE_ADDR val)
struct context *context;
struct frame_state *fs;
+ unwind_tmp_obstack_init ();
+
context = context_alloc ();
fs = frame_state_alloc ();
@@ -1603,6 +1781,8 @@ cfi_frame_chain (struct frame_info *fi)
struct frame_state *fs;
CORE_ADDR cfa;
+ unwind_tmp_obstack_init ();
+
context = context_alloc ();
fs = frame_state_alloc ();
context_cpy (context, UNWIND_CONTEXT (fi));
@@ -1619,7 +1799,7 @@ cfi_frame_chain (struct frame_info *fi)
cfa = context->cfa;
unwind_tmp_obstack_free ();
-
+
return cfa;
}
@@ -1639,6 +1819,8 @@ cfi_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
struct frame_state *fs;
+ unwind_tmp_obstack_init ();
+
fs = frame_state_alloc ();
fi->context = frame_obstack_alloc (sizeof (struct context));
UNWIND_CONTEXT (fi)->reg =
@@ -1658,6 +1840,7 @@ cfi_init_extra_frame_info (int fromleaf, struct frame_info *fi)
frame_state_for (UNWIND_CONTEXT (fi), fs);
update_context (UNWIND_CONTEXT (fi), fs, 0);
}
+
unwind_tmp_obstack_free ();
}
@@ -1678,7 +1861,7 @@ cfi_get_ra (struct frame_info *fi)
void
cfi_get_saved_register (char *raw_buffer,
int *optimized,
- CORE_ADDR * addrp,
+ CORE_ADDR *addrp,
struct frame_info *frame,
int regnum, enum lval_type *lval)
{
@@ -1765,6 +1948,8 @@ cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_reg,
struct context *context;
struct frame_state *fs;
+ unwind_tmp_obstack_init ();
+
context = context_alloc ();
fs = frame_state_alloc ();
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 2b75520059a..85129570169 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2002-07-03 Michal Ludvig <mludvig@suse.cz>
+
+ Merge from mainline:
+
+ 2002-06-06 Michal Ludvig <mludvig@suse.cz>
+ * gdb.asm/asm-source.exp: Add x86-64 target.
+ * gdb.asm/x86_64.inc: New.
+
2002-02-24 Andrew Cagney <ac131313@redhat.com>
* testsuite/gdb.base/huge.c: Replace ``Linux'' with either
diff --git a/gdb/testsuite/gdb.asm/asm-source.exp b/gdb/testsuite/gdb.asm/asm-source.exp
index 471b31a6df6..c0d4914f6fe 100644
--- a/gdb/testsuite/gdb.asm/asm-source.exp
+++ b/gdb/testsuite/gdb.asm/asm-source.exp
@@ -47,6 +47,10 @@ if [istarget "d10v-*-*"] then {
if [istarget "s390-*-*"] then {
set asm-arch s390
}
+if [istarget "x86_64-*-*"] then {
+ set asm-arch x86_64
+ set asm-flags "-gdwarf2 -I${srcdir}/${subdir} -I${objdir}/${subdir}"
+}
if [istarget "i\[3456\]86-*-*"] then {
set asm-arch i386
}
diff --git a/gdb/x86-64-linux-nat.c b/gdb/x86-64-linux-nat.c
index fd705727524..7749b415114 100644
--- a/gdb/x86-64-linux-nat.c
+++ b/gdb/x86-64-linux-nat.c
@@ -25,7 +25,6 @@
#include "inferior.h"
#include "gdbcore.h"
#include "regcache.h"
-#include "i387-nat.h"
#include "gdb_assert.h"
#include "x86-64-tdep.h"
@@ -158,7 +157,7 @@ fill_gregset (elf_gregset_t * gregsetp, int regno)
for (i = 0; i < x86_64_num_gregs; i++)
if ((regno == -1 || regno == i))
- read_register_gen (i, regp + x86_64_regmap[i]);
+ read_register_gen (i, (char *) (regp + x86_64_regmap[i]));
}
/* Fetch all general-purpose registers from process/thread TID and
@@ -195,23 +194,73 @@ store_regs (int tid, int regno)
/* Transfering floating-point registers between GDB, inferiors and cores. */
-/* Fill GDB's register array with the floating-point register values in
- *FPREGSETP. */
+static void *
+x86_64_fxsave_offset (elf_fpregset_t * fxsave, int regnum)
+{
+ const char *reg_name;
+ int reg_index;
+
+ gdb_assert (x86_64_num_gregs - 1 < regnum && regnum < x86_64_num_regs);
+
+ reg_name = x86_64_register_name (regnum);
+
+ if (reg_name[0] == 's' && reg_name[1] == 't')
+ {
+ reg_index = reg_name[2] - '0';
+ return &fxsave->st_space[reg_index * 2];
+ }
+
+ if (reg_name[0] == 'x' && reg_name[1] == 'm' && reg_name[2] == 'm')
+ {
+ reg_index = reg_name[3] - '0';
+ return &fxsave->xmm_space[reg_index * 4];
+ }
+
+ if (strcmp (reg_name, "mxcsr") == 0)
+ return &fxsave->mxcsr;
+
+ return NULL;
+}
+
+/* Fill GDB's register array with the floating-point and SSE register
+ values in *FXSAVE. This function masks off any of the reserved
+ bits in *FXSAVE. */
void
-supply_fpregset (elf_fpregset_t * fpregsetp)
+supply_fpregset (elf_fpregset_t * fxsave)
{
- i387_supply_fxsave ((char *) fpregsetp);
+ int i, reg_st0, reg_mxcsr;
+
+ reg_st0 = x86_64_register_number ("st0");
+ reg_mxcsr = x86_64_register_number ("mxcsr");
+
+ gdb_assert (reg_st0 > 0 && reg_mxcsr > reg_st0);
+
+ for (i = reg_st0; i <= reg_mxcsr; i++)
+ supply_register (i, x86_64_fxsave_offset (fxsave, i));
}
-/* Fill register REGNO (if it is a floating-point register) in
- *FPREGSETP with the value in GDB's register array. If REGNO is -1,
- do this for all registers. */
+/* Fill register REGNUM (if it is a floating-point or SSE register) in
+ *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
+ this for all registers. This function doesn't touch any of the
+ reserved bits in *FXSAVE. */
void
-fill_fpregset (elf_fpregset_t * fpregsetp, int regno)
+fill_fpregset (elf_fpregset_t * fxsave, int regnum)
{
- i387_fill_fxsave ((char *) fpregsetp, regno);
+ int i, last_regnum = MXCSR_REGNUM;
+ void *ptr;
+
+ if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
+ last_regnum = FOP_REGNUM;
+
+ for (i = FP0_REGNUM; i <= last_regnum; i++)
+ if (regnum == -1 || regnum == i)
+ {
+ ptr = x86_64_fxsave_offset (fxsave, i);
+ if (ptr)
+ regcache_collect (i, ptr);
+ }
}
/* Fetch all floating-point registers from process/thread TID and store
@@ -406,12 +455,6 @@ static struct core_fns linux_elf_core_fns = {
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#endif
-/* Record the value of the debug control register. */
-static long debug_control_mirror;
-
-/* Record which address associates with which register. */
-static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
-
/* Return the address of register REGNUM. BLOCKEND is the value of
u.u_ar0, which should point to the registers. */
CORE_ADDR
@@ -446,4 +489,3 @@ kernel_u_size (void)
{
return (sizeof (struct user));
}
-
diff --git a/gdb/x86-64-tdep.c b/gdb/x86-64-tdep.c
index 3ebc1b2594a..b1bb1477dd6 100644
--- a/gdb/x86-64-tdep.c
+++ b/gdb/x86-64-tdep.c
@@ -37,6 +37,7 @@
#define RDX_REGNUM 3
#define RDI_REGNUM 5
#define EFLAGS_REGNUM 17
+#define ST0_REGNUM 22
#define XMM1_REGNUM 39
struct register_info
@@ -49,63 +50,90 @@ struct register_info
/* x86_64_register_raw_size_table[i] is the number of bytes of storage in
GDB's register array occupied by register i. */
static struct register_info x86_64_register_info_table[] = {
- {8, "rax", &builtin_type_int64},
- {8, "rbx", &builtin_type_int64},
- {8, "rcx", &builtin_type_int64},
- {8, "rdx", &builtin_type_int64},
- {8, "rsi", &builtin_type_int64},
- {8, "rdi", &builtin_type_int64},
- {8, "rbp", &builtin_type_void_func_ptr},
- {8, "rsp", &builtin_type_void_func_ptr},
- {8, "r8", &builtin_type_int64},
- {8, "r9", &builtin_type_int64},
- {8, "r10", &builtin_type_int64},
- {8, "r11", &builtin_type_int64},
- {8, "r12", &builtin_type_int64},
- {8, "r13", &builtin_type_int64},
- {8, "r14", &builtin_type_int64},
- {8, "r15", &builtin_type_int64},
- {8, "rip", &builtin_type_void_func_ptr},
- {4, "eflags", &builtin_type_int32},
- {4, "ds", &builtin_type_int32},
- {4, "es", &builtin_type_int32},
- {4, "fs", &builtin_type_int32},
- {4, "gs", &builtin_type_int32},
- {10, "st0", &builtin_type_i387_ext},
- {10, "st1", &builtin_type_i387_ext},
- {10, "st2", &builtin_type_i387_ext},
- {10, "st3", &builtin_type_i387_ext},
- {10, "st4", &builtin_type_i387_ext},
- {10, "st5", &builtin_type_i387_ext},
- {10, "st6", &builtin_type_i387_ext},
- {10, "st7", &builtin_type_i387_ext},
- {4, "fctrl", &builtin_type_int32},
- {4, "fstat", &builtin_type_int32},
- {4, "ftag", &builtin_type_int32},
- {4, "fiseg", &builtin_type_int32},
- {4, "fioff", &builtin_type_int32},
- {4, "foseg", &builtin_type_int32},
- {4, "fooff", &builtin_type_int32},
- {4, "fop", &builtin_type_int32},
- {16, "xmm0", &builtin_type_v4sf},
- {16, "xmm1", &builtin_type_v4sf},
- {16, "xmm2", &builtin_type_v4sf},
- {16, "xmm3", &builtin_type_v4sf},
- {16, "xmm4", &builtin_type_v4sf},
- {16, "xmm5", &builtin_type_v4sf},
- {16, "xmm6", &builtin_type_v4sf},
- {16, "xmm7", &builtin_type_v4sf},
- {16, "xmm8", &builtin_type_v4sf},
- {16, "xmm9", &builtin_type_v4sf},
- {16, "xmm10", &builtin_type_v4sf},
- {16, "xmm11", &builtin_type_v4sf},
- {16, "xmm12", &builtin_type_v4sf},
- {16, "xmm13", &builtin_type_v4sf},
- {16, "xmm14", &builtin_type_v4sf},
- {16, "xmm15", &builtin_type_v4sf},
- {4, "mxcsr", &builtin_type_int32}
+ /* 0 */ {8, "rax", &builtin_type_int64},
+ /* 1 */ {8, "rbx", &builtin_type_int64},
+ /* 2 */ {8, "rcx", &builtin_type_int64},
+ /* 3 */ {8, "rdx", &builtin_type_int64},
+ /* 4 */ {8, "rsi", &builtin_type_int64},
+ /* 5 */ {8, "rdi", &builtin_type_int64},
+ /* 6 */ {8, "rbp", &builtin_type_void_func_ptr},
+ /* 7 */ {8, "rsp", &builtin_type_void_func_ptr},
+ /* 8 */ {8, "r8", &builtin_type_int64},
+ /* 9 */ {8, "r9", &builtin_type_int64},
+ /* 10 */ {8, "r10", &builtin_type_int64},
+ /* 11 */ {8, "r11", &builtin_type_int64},
+ /* 12 */ {8, "r12", &builtin_type_int64},
+ /* 13 */ {8, "r13", &builtin_type_int64},
+ /* 14 */ {8, "r14", &builtin_type_int64},
+ /* 15 */ {8, "r15", &builtin_type_int64},
+ /* 16 */ {8, "rip", &builtin_type_void_func_ptr},
+ /* 17 */ {4, "eflags", &builtin_type_int32},
+ /* 18 */ {4, "ds", &builtin_type_int32},
+ /* 19 */ {4, "es", &builtin_type_int32},
+ /* 20 */ {4, "fs", &builtin_type_int32},
+ /* 21 */ {4, "gs", &builtin_type_int32},
+ /* 22 */ {10, "st0", &builtin_type_i387_ext},
+ /* 23 */ {10, "st1", &builtin_type_i387_ext},
+ /* 24 */ {10, "st2", &builtin_type_i387_ext},
+ /* 25 */ {10, "st3", &builtin_type_i387_ext},
+ /* 26 */ {10, "st4", &builtin_type_i387_ext},
+ /* 27 */ {10, "st5", &builtin_type_i387_ext},
+ /* 28 */ {10, "st6", &builtin_type_i387_ext},
+ /* 29 */ {10, "st7", &builtin_type_i387_ext},
+ /* 30 */ {4, "fctrl", &builtin_type_int32},
+ /* 31 */ {4, "fstat", &builtin_type_int32},
+ /* 32 */ {4, "ftag", &builtin_type_int32},
+ /* 33 */ {4, "fiseg", &builtin_type_int32},
+ /* 34 */ {4, "fioff", &builtin_type_int32},
+ /* 35 */ {4, "foseg", &builtin_type_int32},
+ /* 36 */ {4, "fooff", &builtin_type_int32},
+ /* 37 */ {4, "fop", &builtin_type_int32},
+ /* 38 */ {16, "xmm0", &builtin_type_v4sf},
+ /* 39 */ {16, "xmm1", &builtin_type_v4sf},
+ /* 40 */ {16, "xmm2", &builtin_type_v4sf},
+ /* 41 */ {16, "xmm3", &builtin_type_v4sf},
+ /* 42 */ {16, "xmm4", &builtin_type_v4sf},
+ /* 43 */ {16, "xmm5", &builtin_type_v4sf},
+ /* 44 */ {16, "xmm6", &builtin_type_v4sf},
+ /* 45 */ {16, "xmm7", &builtin_type_v4sf},
+ /* 46 */ {16, "xmm8", &builtin_type_v4sf},
+ /* 47 */ {16, "xmm9", &builtin_type_v4sf},
+ /* 48 */ {16, "xmm10", &builtin_type_v4sf},
+ /* 49 */ {16, "xmm11", &builtin_type_v4sf},
+ /* 50 */ {16, "xmm12", &builtin_type_v4sf},
+ /* 51 */ {16, "xmm13", &builtin_type_v4sf},
+ /* 52 */ {16, "xmm14", &builtin_type_v4sf},
+ /* 53 */ {16, "xmm15", &builtin_type_v4sf},
+ /* 54 */ {4, "mxcsr", &builtin_type_int32}
};
+/* This array is a mapping from Dwarf-2 register
+ numbering to GDB's one. Dwarf-2 numbering is
+ defined in x86-64 ABI, section 3.6. */
+static int x86_64_dwarf2gdb_regno_map[] = {
+ 0, 1, 2, 3, /* RAX - RDX */
+ 4, 5, 6, 7, /* RSI, RDI, RBP, RSP */
+ 8, 9, 10, 11, /* R8 - R11 */
+ 12, 13, 14, 15, /* R12 - R15 */
+ -1, /* RA - not mapped */
+ XMM1_REGNUM - 1, XMM1_REGNUM, /* XMM0 ... */
+ XMM1_REGNUM + 1, XMM1_REGNUM + 2,
+ XMM1_REGNUM + 3, XMM1_REGNUM + 4,
+ XMM1_REGNUM + 5, XMM1_REGNUM + 6,
+ XMM1_REGNUM + 7, XMM1_REGNUM + 8,
+ XMM1_REGNUM + 9, XMM1_REGNUM + 10,
+ XMM1_REGNUM + 11, XMM1_REGNUM + 12,
+ XMM1_REGNUM + 13, XMM1_REGNUM + 14, /* ... XMM15 */
+ ST0_REGNUM + 0, ST0_REGNUM + 1, /* ST0 ... */
+ ST0_REGNUM + 2, ST0_REGNUM + 3,
+ ST0_REGNUM + 4, ST0_REGNUM + 5,
+ ST0_REGNUM + 6, ST0_REGNUM + 7 /* ... ST7 */
+};
+
+static int x86_64_dwarf2gdb_regno_map_length =
+ sizeof (x86_64_dwarf2gdb_regno_map) /
+ sizeof (x86_64_dwarf2gdb_regno_map[0]);
+
/* Number of all registers */
#define X86_64_NUM_REGS (sizeof (x86_64_register_info_table) / \
sizeof (x86_64_register_info_table[0]))
@@ -167,7 +195,7 @@ x86_64_register_convert_to_virtual (int regnum, struct type *type,
char *from, char *to)
{
char buf[12];
- DOUBLEST d;
+
/* We only support floating-point values. */
if (TYPE_CODE (type) != TYPE_CODE_FLT)
{
@@ -198,6 +226,19 @@ x86_64_register_convert_to_raw (struct type *type, int regnum,
memcpy (to, from, FPU_REG_RAW_SIZE);
}
+/* Dwarf-2 <-> GDB register numbers mapping. */
+int
+x86_64_dwarf2_reg_to_regnum (int dw_reg)
+{
+ if (dw_reg < 0 || dw_reg > x86_64_dwarf2gdb_regno_map_length)
+ {
+ warning ("Dwarf-2 uses unmapped register #%d\n", dw_reg);
+ return dw_reg;
+ }
+
+ return x86_64_dwarf2gdb_regno_map[dw_reg];
+}
+
/* This is the variable that is set with "set disassembly-flavour", and
its legitimate values. */
static const char att_flavour[] = "att";
@@ -331,18 +372,19 @@ classify_argument (struct type *type,
case TYPE_CODE_STRUCT:
{
int j;
- for (j = 0; j < type->nfields; ++j)
+ for (j = 0; j < TYPE_NFIELDS (type); ++j)
{
- int num = classify_argument (type->fields[j].type,
+ int num = classify_argument (TYPE_FIELDS (type)[j].type,
subclasses,
- (type->fields[j].loc.bitpos
- + bit_offset) % 256);
+ (TYPE_FIELDS (type)[j].loc.
+ bitpos + bit_offset) % 256);
if (!num)
return 0;
for (i = 0; i < num; i++)
{
int pos =
- (type->fields[j].loc.bitpos + bit_offset) / 8 / 8;
+ (TYPE_FIELDS (type)[j].loc.bitpos +
+ bit_offset) / 8 / 8;
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
}
@@ -353,7 +395,7 @@ classify_argument (struct type *type,
{
int num;
- num = classify_argument (type->target_type,
+ num = classify_argument (TYPE_TARGET_TYPE (type),
subclasses, bit_offset);
if (!num)
return 0;
@@ -372,10 +414,10 @@ classify_argument (struct type *type,
{
int j;
{
- for (j = 0; j < type->nfields; ++j)
+ for (j = 0; j < TYPE_NFIELDS (type); ++j)
{
int num;
- num = classify_argument (type->fields[j].type,
+ num = classify_argument (TYPE_FIELDS (type)[j].type,
subclasses, bit_offset);
if (!num)
return 0;
@@ -385,6 +427,8 @@ classify_argument (struct type *type,
}
}
break;
+ default:
+ break;
}
/* Final merger cleanup. */
for (i = 0; i < words; i++)
@@ -447,6 +491,8 @@ classify_argument (struct type *type,
}
case TYPE_CODE_VOID:
return 0;
+ default: /* Avoid warning. */
+ break;
}
internal_error (__FILE__, __LINE__,
"classify_argument: unknown argument type");
@@ -609,7 +655,7 @@ x86_64_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
static int int_parameter_registers[INT_REGS] = {
5 /* RDI */ , 4 /* RSI */ ,
3 /* RDX */ , 2 /* RCX */ ,
- 8 /* R8 */ , 9 /* R9 */
+ 8 /* R8 */ , 9 /* R9 */
};
/* XMM0 - XMM15 */
static int sse_parameter_registers[SSE_REGS] = {
@@ -752,13 +798,24 @@ x86_64_store_return_value (struct type *type, char *valbuf)
}
-static char *
+char *
x86_64_register_name (int reg_nr)
{
if (reg_nr < 0 || reg_nr >= X86_64_NUM_REGS)
return NULL;
return x86_64_register_info_table[reg_nr].name;
}
+
+int
+x86_64_register_number (const char *name)
+{
+ int reg_nr;
+
+ for (reg_nr = 0; reg_nr < X86_64_NUM_REGS; reg_nr++)
+ if (strcmp (name, x86_64_register_info_table[reg_nr].name) == 0)
+ return reg_nr;
+ return -1;
+}
@@ -800,10 +857,10 @@ x86_64_frameless_function_invocation (struct frame_info *frame)
CORE_ADDR
x86_64_skip_prologue (CORE_ADDR pc)
{
- int i, firstline, currline;
+ int i;
struct symtab_and_line v_sal;
struct symbol *v_function;
- CORE_ADDR salendaddr = 0, endaddr = 0;
+ CORE_ADDR endaddr;
/* We will handle only functions beginning with:
55 pushq %rbp
@@ -817,7 +874,7 @@ x86_64_skip_prologue (CORE_ADDR pc)
/* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */
for (i = 0; i < PROLOG_BUFSIZE; i++)
if (prolog_expect[i] != prolog_buf[i])
- return pc; /* ... no, it doesn't. Nothing to skip. */
+ return pc; /* ... no, it doesn't. Nothing to skip. */
/* OK, we have found the prologue and want PC of the first
non-prologue instruction. */
@@ -831,18 +888,13 @@ x86_64_skip_prologue (CORE_ADDR pc)
if (!v_function || !v_function->ginfo.value.block || !v_sal.symtab)
return pc;
- firstline = v_sal.line;
- currline = firstline;
- salendaddr = v_sal.end;
endaddr = v_function->ginfo.value.block->endaddr;
for (i = 0; i < v_sal.symtab->linetable->nitems; i++)
- if (v_sal.symtab->linetable->item[i].line > firstline
- && v_sal.symtab->linetable->item[i].pc >= salendaddr
+ if (v_sal.symtab->linetable->item[i].pc >= pc
&& v_sal.symtab->linetable->item[i].pc < endaddr)
{
pc = v_sal.symtab->linetable->item[i].pc;
- currline = v_sal.symtab->linetable->item[i].line;
break;
}
@@ -859,7 +911,7 @@ x86_64_breakpoint_from_pc (CORE_ADDR * pc, int *lenptr)
}
static struct gdbarch *
-i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
@@ -885,7 +937,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
break;
default:
internal_error (__FILE__, __LINE__,
- "i386_gdbarch_init: unknown machine type");
+ "x86_64_gdbarch_init: unknown machine type");
}
break;
case bfd_mach_i386_i386:
@@ -902,12 +954,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
return arches->gdbarch;
default:
internal_error (__FILE__, __LINE__,
- "i386_gdbarch_init: unknown machine type");
+ "x86_64_gdbarch_init: unknown machine type");
}
break;
default:
internal_error (__FILE__, __LINE__,
- "i386_gdbarch_init: unknown machine type");
+ "x86_64_gdbarch_init: unknown machine type");
}
}
@@ -927,7 +979,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
break;
default:
internal_error (__FILE__, __LINE__,
- "i386_gdbarch_init: unknown machine type");
+ "x86_64_gdbarch_init: unknown machine type");
}
set_gdbarch_long_bit (gdbarch, 64);
@@ -967,7 +1019,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_fp0_regnum (gdbarch, X86_64_NUM_GREGS); /* First FPU floating-point register. */
set_gdbarch_read_fp (gdbarch, cfi_read_fp);
- set_gdbarch_write_fp (gdbarch, cfi_write_fp);
/* Discard from the stack the innermost frame, restoring all registers. */
set_gdbarch_pop_frame (gdbarch, x86_64_pop_frame);
@@ -1056,7 +1107,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_breakpoint_from_pc (gdbarch, x86_64_breakpoint_from_pc);
+ set_gdbarch_breakpoint_from_pc (gdbarch,
+ (gdbarch_breakpoint_from_pc_ftype *)
+ x86_64_breakpoint_from_pc);
/* Amount PC must be decremented by after a breakpoint. This is often the
@@ -1065,13 +1118,15 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Use dwarf2 debug frame informations. */
set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum);
+
return gdbarch;
}
void
_initialize_x86_64_tdep (void)
{
- register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
+ register_gdbarch_init (bfd_arch_i386, x86_64_gdbarch_init);
/* Initialize the table saying where each register starts in the
register file. */
diff --git a/gdb/x86-64-tdep.h b/gdb/x86-64-tdep.h
index d15b8e71e7f..edbfdf36f75 100644
--- a/gdb/x86-64-tdep.h
+++ b/gdb/x86-64-tdep.h
@@ -28,6 +28,10 @@
extern int x86_64_num_regs;
extern int x86_64_num_gregs;
+int x86_64_register_number (const char *name);
+char *x86_64_register_name (int reg_nr);
+
+
gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;