mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-30 05:23:49 +08:00
bd2b40ac12
This changes GDB to use frame_info_ptr instead of frame_info * The substitution was done with multiple sequential `sed` commands: sed 's/^struct frame_info;/class frame_info_ptr;/' sed 's/struct frame_info \*/frame_info_ptr /g' - which left some issues in a few files, that were manually fixed. sed 's/\<frame_info \*/frame_info_ptr /g' sed 's/frame_info_ptr $/frame_info_ptr/g' - used to remove whitespace problems. The changed files were then manually checked and some 'sed' changes undone, some constructors and some gets were added, according to what made sense, and what Tromey originally did Co-Authored-By: Bruno Larsen <blarsen@redhat.com> Approved-by: Tom Tomey <tom@tromey.com>
229 lines
6.5 KiB
C
229 lines
6.5 KiB
C
/* Target-dependent code for Windows (including Cygwin) running on i386's,
|
|
for GDB.
|
|
|
|
Copyright (C) 2003-2022 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "defs.h"
|
|
#include "osabi.h"
|
|
#include "i386-tdep.h"
|
|
#include "windows-tdep.h"
|
|
#include "regset.h"
|
|
#include "gdbsupport/gdb_obstack.h"
|
|
#include "xml-support.h"
|
|
#include "gdbcore.h"
|
|
#include "inferior.h"
|
|
|
|
/* Core file support. */
|
|
|
|
/* This vector maps GDB's idea of a register's number into an address
|
|
in the windows exception context vector. */
|
|
|
|
static int i386_windows_gregset_reg_offset[] =
|
|
{
|
|
176, /* eax */
|
|
172, /* ecx */
|
|
168, /* edx */
|
|
164, /* ebx */
|
|
|
|
196, /* esp */
|
|
180, /* ebp */
|
|
160, /* esi */
|
|
156, /* edi */
|
|
|
|
184, /* eip */
|
|
192, /* eflags */
|
|
188, /* cs */
|
|
200, /* ss */
|
|
|
|
152, /* ds */
|
|
148, /* es */
|
|
144, /* fs */
|
|
140, /* gs */
|
|
|
|
56, /* FloatSave.RegisterArea[0 * 10] */
|
|
66, /* FloatSave.RegisterArea[1 * 10] */
|
|
76, /* FloatSave.RegisterArea[2 * 10] */
|
|
86, /* FloatSave.RegisterArea[3 * 10] */
|
|
96, /* FloatSave.RegisterArea[4 * 10] */
|
|
106, /* FloatSave.RegisterArea[5 * 10] */
|
|
116, /* FloatSave.RegisterArea[6 * 10] */
|
|
126, /* FloatSave.RegisterArea[7 * 10] */
|
|
|
|
28, /* FloatSave.ControlWord */
|
|
32, /* FloatSave.StatusWord */
|
|
36, /* FloatSave.TagWord */
|
|
44, /* FloatSave.ErrorSelector */
|
|
40, /* FloatSave.ErrorOffset */
|
|
52, /* FloatSave.DataSelector */
|
|
48, /* FloatSave.DataOffset */
|
|
44, /* FloatSave.ErrorSelector */
|
|
|
|
/* XMM0-7 */
|
|
364, /* ExtendedRegisters[10*16] */
|
|
380, /* ExtendedRegisters[11*16] */
|
|
396, /* ExtendedRegisters[12*16] */
|
|
412, /* ExtendedRegisters[13*16] */
|
|
428, /* ExtendedRegisters[14*16] */
|
|
444, /* ExtendedRegisters[15*16] */
|
|
460, /* ExtendedRegisters[16*16] */
|
|
476, /* ExtendedRegisters[17*16] */
|
|
|
|
/* MXCSR */
|
|
228 /* ExtendedRegisters[24] */
|
|
};
|
|
|
|
#define I386_WINDOWS_SIZEOF_GREGSET 716
|
|
|
|
static CORE_ADDR
|
|
i386_windows_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc)
|
|
{
|
|
return i386_pe_skip_trampoline_code (frame, pc, NULL);
|
|
}
|
|
|
|
static const char *
|
|
i386_windows_auto_wide_charset (void)
|
|
{
|
|
return "UTF-16";
|
|
}
|
|
|
|
/* Implement the "push_dummy_call" gdbarch method. */
|
|
|
|
static CORE_ADDR
|
|
i386_windows_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|
struct regcache *regcache, CORE_ADDR bp_addr,
|
|
int nargs, struct value **args, CORE_ADDR sp,
|
|
function_call_return_method return_method,
|
|
CORE_ADDR struct_addr)
|
|
{
|
|
/* For non-static member functions of 32bit Windows programs, the thiscall
|
|
calling convention is used, so the 'this' pointer is passed in ECX. */
|
|
bool thiscall = false;
|
|
|
|
struct type *type = check_typedef (value_type (function));
|
|
if (type->code () == TYPE_CODE_PTR)
|
|
type = check_typedef (type->target_type ());
|
|
|
|
/* read_subroutine_type sets for non-static member functions the
|
|
artificial flag of the first parameter ('this' pointer). */
|
|
if (type->code () == TYPE_CODE_METHOD
|
|
&& type->num_fields () > 0
|
|
&& TYPE_FIELD_ARTIFICIAL (type, 0)
|
|
&& type->field (0).type ()->code () == TYPE_CODE_PTR)
|
|
thiscall = 1;
|
|
|
|
return i386_thiscall_push_dummy_call (gdbarch, function, regcache, bp_addr,
|
|
nargs, args, sp, return_method,
|
|
struct_addr, thiscall);
|
|
}
|
|
|
|
/* Common parts for gdbarch initialization for Windows and Cygwin on i386. */
|
|
|
|
static void
|
|
i386_windows_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
{
|
|
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
|
|
|
|
set_gdbarch_skip_trampoline_code (gdbarch, i386_windows_skip_trampoline_code);
|
|
|
|
set_gdbarch_skip_main_prologue (gdbarch, i386_skip_main_prologue);
|
|
|
|
tdep->struct_return = reg_struct_return;
|
|
|
|
tdep->gregset_reg_offset = i386_windows_gregset_reg_offset;
|
|
tdep->gregset_num_regs = ARRAY_SIZE (i386_windows_gregset_reg_offset);
|
|
tdep->sizeof_gregset = I386_WINDOWS_SIZEOF_GREGSET;
|
|
|
|
tdep->sizeof_fpregset = 0;
|
|
|
|
/* Core file support. */
|
|
set_gdbarch_core_xfer_shared_libraries
|
|
(gdbarch, windows_core_xfer_shared_libraries);
|
|
set_gdbarch_core_pid_to_str (gdbarch, windows_core_pid_to_str);
|
|
|
|
set_gdbarch_auto_wide_charset (gdbarch, i386_windows_auto_wide_charset);
|
|
}
|
|
|
|
/* gdbarch initialization for Windows on i386. */
|
|
|
|
static void
|
|
i386_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
{
|
|
i386_windows_init_abi_common (info, gdbarch);
|
|
windows_init_abi (info, gdbarch);
|
|
|
|
set_gdbarch_push_dummy_call (gdbarch, i386_windows_push_dummy_call);
|
|
}
|
|
|
|
/* gdbarch initialization for Cygwin on i386. */
|
|
|
|
static void
|
|
i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
{
|
|
i386_windows_init_abi_common (info, gdbarch);
|
|
cygwin_init_abi (info, gdbarch);
|
|
}
|
|
|
|
static gdb_osabi
|
|
i386_windows_osabi_sniffer (bfd *abfd)
|
|
{
|
|
const char *target_name = bfd_get_target (abfd);
|
|
|
|
if (!streq (target_name, "pei-i386"))
|
|
return GDB_OSABI_UNKNOWN;
|
|
|
|
if (is_linked_with_cygwin_dll (abfd))
|
|
return GDB_OSABI_CYGWIN;
|
|
|
|
return GDB_OSABI_WINDOWS;
|
|
}
|
|
|
|
static enum gdb_osabi
|
|
i386_cygwin_core_osabi_sniffer (bfd *abfd)
|
|
{
|
|
const char *target_name = bfd_get_target (abfd);
|
|
|
|
/* Cygwin uses elf core dumps. Do not claim all ELF executables,
|
|
check whether there is a .reg section of proper size. */
|
|
if (strcmp (target_name, "elf32-i386") == 0)
|
|
{
|
|
asection *section = bfd_get_section_by_name (abfd, ".reg");
|
|
if (section != nullptr
|
|
&& bfd_section_size (section) == I386_WINDOWS_SIZEOF_GREGSET)
|
|
return GDB_OSABI_CYGWIN;
|
|
}
|
|
|
|
return GDB_OSABI_UNKNOWN;
|
|
}
|
|
|
|
void _initialize_i386_windows_tdep ();
|
|
void
|
|
_initialize_i386_windows_tdep ()
|
|
{
|
|
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
|
|
i386_windows_osabi_sniffer);
|
|
|
|
/* Cygwin uses elf core dumps. */
|
|
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
|
|
i386_cygwin_core_osabi_sniffer);
|
|
|
|
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_WINDOWS,
|
|
i386_windows_init_abi);
|
|
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
|
|
i386_cygwin_init_abi);
|
|
}
|