blob: 53dc8f9f253bc94ca38354b33b667f8b8441cf6c [file] [log] [blame]
/* Target-dependent code for NaCl.
Copyright (C) 2001, 2003-2012 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 "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
#include "amd64-tdep.h"
#include "nacl-manifest.h"
#include "symtab.h"
#include "solib-svr4.h"
#include "frame.h"
#include "osabi.h"
static void
nacl_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
/* NaCl uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_solib_svr4_map_so_name (gdbarch, nacl_manifest_find);
set_gdbarch_process_record (gdbarch, i386_process_record);
}
static void
i386_nacl_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
linux_init_abi (info, gdbarch);
i386_elf_init_abi (info, gdbarch);
tdep->tdesc = tdesc_i386_linux;
set_solib_svr4_fetch_link_map_offsets (gdbarch,
svr4_ilp32_fetch_link_map_offsets);
nacl_init_abi (info, gdbarch);
}
static CORE_ADDR
amd64_nacl_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
{
return val & 0xffffffffUL;
}
static CORE_ADDR
amd64_nacl_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
CORE_ADDR pc;
pc = frame_unwind_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
return amd64_nacl_addr_bits_remove (gdbarch, pc);
}
static CORE_ADDR
amd64_nacl_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
CORE_ADDR sp;
sp = frame_unwind_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
return amd64_nacl_addr_bits_remove (gdbarch, sp);
}
struct link_map_offsets *
amd64_nacl_fetch_link_map_offsets (void)
{
static struct link_map_offsets lmo;
static struct link_map_offsets *lmp = NULL;
if (lmp == NULL)
{
lmp = &lmo;
lmo.r_version_offset = 0;
lmo.r_version_size = 4;
lmo.r_map_offset = 4;
lmo.r_brk_offset = 8;
/* Dynamic linker is in the normal list of shared objects. */
lmo.r_ldsomap_offset = -1;
lmo.link_map_size = 24;
lmo.l_addr_offset = 0;
lmo.l_name_offset = 8;
lmo.l_ld_offset = 12;
lmo.l_next_offset = 16;
lmo.l_prev_offset = 20;
}
return lmp;
}
static void
amd64_nacl_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
linux_init_abi (info, gdbarch);
amd64_init_abi (info, gdbarch);
tdep->tdesc = tdesc_amd64_linux;
set_solib_svr4_fetch_link_map_offsets (gdbarch,
amd64_nacl_fetch_link_map_offsets);
nacl_init_abi (info, gdbarch);
/* NaCl data model.
WARNING! This might confuse a lot of code, as it uses
if (set_gdbarch_ptr_bit (gdbarch) == <bits>)
to distinguish between i386 and x86_64 (lame!). Luckily, most of that
code is about native debugging and syscalls, so it is not used for NaCl.
TODO(eaeltsin): find better way to distinguish between i386 and x86_64! */
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 32);
/* TODO(eaeltsin): we might use address size instead of pointer size to
distinguish between i386 and x86_64... At least address size is not
a property of the data model. */
set_gdbarch_addr_bit (gdbarch, 64);
/* How to extract addresses from registers. */
set_gdbarch_addr_bits_remove (gdbarch, amd64_nacl_addr_bits_remove);
set_gdbarch_unwind_pc (gdbarch, amd64_nacl_unwind_pc);
set_gdbarch_unwind_sp (gdbarch, amd64_nacl_unwind_sp);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
extern void _initialize_nacl_tdep (void);
void
_initialize_nacl_tdep (void)
{
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_NACL, amd64_nacl_init_abi);
gdbarch_register_osabi (bfd_arch_i386, 0,
GDB_OSABI_NACL, i386_nacl_init_abi);
}