GDBserver
|
00001 /* GNU/Linux/x86 specific low level interface, for the in-process 00002 agent library for GDB. 00003 00004 Copyright (C) 2010-2013 Free Software Foundation, Inc. 00005 00006 This file is part of GDB. 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00020 00021 #include "server.h" 00022 #include <stdint.h> 00023 #include <sys/mman.h> 00024 #include "tracepoint.h" 00025 00026 /* GDB register numbers. */ 00027 00028 enum i386_gdb_regnum 00029 { 00030 I386_EAX_REGNUM, /* %eax */ 00031 I386_ECX_REGNUM, /* %ecx */ 00032 I386_EDX_REGNUM, /* %edx */ 00033 I386_EBX_REGNUM, /* %ebx */ 00034 I386_ESP_REGNUM, /* %esp */ 00035 I386_EBP_REGNUM, /* %ebp */ 00036 I386_ESI_REGNUM, /* %esi */ 00037 I386_EDI_REGNUM, /* %edi */ 00038 I386_EIP_REGNUM, /* %eip */ 00039 I386_EFLAGS_REGNUM, /* %eflags */ 00040 I386_CS_REGNUM, /* %cs */ 00041 I386_SS_REGNUM, /* %ss */ 00042 I386_DS_REGNUM, /* %ds */ 00043 I386_ES_REGNUM, /* %es */ 00044 I386_FS_REGNUM, /* %fs */ 00045 I386_GS_REGNUM, /* %gs */ 00046 I386_ST0_REGNUM /* %st(0) */ 00047 }; 00048 00049 #define i386_num_regs 16 00050 00051 /* Defined in auto-generated file i386-linux.c. */ 00052 void init_registers_i386_linux (void); 00053 extern const struct target_desc *tdesc_i386_linux; 00054 00055 #define FT_CR_EAX 15 00056 #define FT_CR_ECX 14 00057 #define FT_CR_EDX 13 00058 #define FT_CR_EBX 12 00059 #define FT_CR_UESP 11 00060 #define FT_CR_EBP 10 00061 #define FT_CR_ESI 9 00062 #define FT_CR_EDI 8 00063 #define FT_CR_EIP 7 00064 #define FT_CR_EFL 6 00065 #define FT_CR_DS 5 00066 #define FT_CR_ES 4 00067 #define FT_CR_FS 3 00068 #define FT_CR_GS 2 00069 #define FT_CR_SS 1 00070 #define FT_CR_CS 0 00071 00072 /* Mapping between the general-purpose registers in jump tracepoint 00073 format and GDB's register array layout. */ 00074 00075 static const int i386_ft_collect_regmap[] = 00076 { 00077 FT_CR_EAX * 4, FT_CR_ECX * 4, FT_CR_EDX * 4, FT_CR_EBX * 4, 00078 FT_CR_UESP * 4, FT_CR_EBP * 4, FT_CR_ESI * 4, FT_CR_EDI * 4, 00079 FT_CR_EIP * 4, FT_CR_EFL * 4, FT_CR_CS * 4, FT_CR_SS * 4, 00080 FT_CR_DS * 4, FT_CR_ES * 4, FT_CR_FS * 4, FT_CR_GS * 4 00081 }; 00082 00083 void 00084 supply_fast_tracepoint_registers (struct regcache *regcache, 00085 const unsigned char *buf) 00086 { 00087 int i; 00088 00089 for (i = 0; i < i386_num_regs; i++) 00090 { 00091 int regval; 00092 00093 if (i >= I386_CS_REGNUM && i <= I386_GS_REGNUM) 00094 regval = *(short *) (((char *) buf) + i386_ft_collect_regmap[i]); 00095 else 00096 regval = *(int *) (((char *) buf) + i386_ft_collect_regmap[i]); 00097 00098 supply_register (regcache, i, ®val); 00099 } 00100 } 00101 00102 ULONGEST __attribute__ ((visibility("default"), used)) 00103 gdb_agent_get_raw_reg (unsigned char *raw_regs, int regnum) 00104 { 00105 /* This should maybe be allowed to return an error code, or perhaps 00106 better, have the emit_reg detect this, and emit a constant zero, 00107 or something. */ 00108 00109 if (regnum > i386_num_regs) 00110 return 0; 00111 else if (regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM) 00112 return *(short *) (raw_regs + i386_ft_collect_regmap[regnum]); 00113 else 00114 return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]); 00115 } 00116 00117 #ifdef HAVE_UST 00118 00119 #include <ust/processor.h> 00120 00121 /* "struct registers" is the UST object type holding the registers at 00122 the time of the static tracepoint marker call. This doesn't 00123 contain EIP, but we know what it must have been (the marker 00124 address). */ 00125 00126 #define ST_REGENTRY(REG) \ 00127 { \ 00128 offsetof (struct registers, REG), \ 00129 sizeof (((struct registers *) NULL)->REG) \ 00130 } 00131 00132 static struct 00133 { 00134 int offset; 00135 int size; 00136 } i386_st_collect_regmap[] = 00137 { 00138 ST_REGENTRY(eax), 00139 ST_REGENTRY(ecx), 00140 ST_REGENTRY(edx), 00141 ST_REGENTRY(ebx), 00142 ST_REGENTRY(esp), 00143 ST_REGENTRY(ebp), 00144 ST_REGENTRY(esi), 00145 ST_REGENTRY(edi), 00146 { -1, 0 }, /* eip */ 00147 ST_REGENTRY(eflags), 00148 ST_REGENTRY(cs), 00149 ST_REGENTRY(ss), 00150 }; 00151 00152 #define i386_NUM_ST_COLLECT_GREGS \ 00153 (sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0])) 00154 00155 void 00156 supply_static_tracepoint_registers (struct regcache *regcache, 00157 const unsigned char *buf, 00158 CORE_ADDR pc) 00159 { 00160 int i; 00161 unsigned int newpc = pc; 00162 00163 supply_register (regcache, I386_EIP_REGNUM, &newpc); 00164 00165 for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++) 00166 if (i386_st_collect_regmap[i].offset != -1) 00167 { 00168 switch (i386_st_collect_regmap[i].size) 00169 { 00170 case 4: 00171 supply_register (regcache, i, 00172 ((char *) buf) 00173 + i386_st_collect_regmap[i].offset); 00174 break; 00175 case 2: 00176 { 00177 unsigned long reg 00178 = * (short *) (((char *) buf) 00179 + i386_st_collect_regmap[i].offset); 00180 reg &= 0xffff; 00181 supply_register (regcache, i, ®); 00182 } 00183 break; 00184 default: 00185 internal_error (__FILE__, __LINE__, "unhandled register size: %d", 00186 i386_st_collect_regmap[i].size); 00187 } 00188 } 00189 } 00190 00191 #endif /* HAVE_UST */ 00192 00193 00194 /* This is only needed because reg-i386-linux-lib.o references it. We 00195 may use it proper at some point. */ 00196 const char *gdbserver_xmltarget; 00197 00198 /* Attempt to allocate memory for trampolines in the first 64 KiB of 00199 memory to enable smaller jump patches. */ 00200 00201 static void 00202 initialize_fast_tracepoint_trampoline_buffer (void) 00203 { 00204 const CORE_ADDR buffer_end = 64 * 1024; 00205 /* Ensure that the buffer will be at least 1 KiB in size, which is 00206 enough space for over 200 fast tracepoints. */ 00207 const int min_buffer_size = 1024; 00208 char buf[IPA_BUFSIZ]; 00209 CORE_ADDR mmap_min_addr = buffer_end + 1; 00210 ULONGEST buffer_size; 00211 FILE *f = fopen ("/proc/sys/vm/mmap_min_addr", "r"); 00212 00213 if (!f) 00214 { 00215 snprintf (buf, sizeof (buf), "mmap_min_addr open failed: %s", 00216 strerror (errno)); 00217 set_trampoline_buffer_space (0, 0, buf); 00218 return; 00219 } 00220 00221 if (fgets (buf, IPA_BUFSIZ, f)) 00222 sscanf (buf, "%llu", &mmap_min_addr); 00223 00224 fclose (f); 00225 00226 buffer_size = buffer_end - mmap_min_addr; 00227 00228 if (buffer_size >= min_buffer_size) 00229 { 00230 if (mmap ((void *) (uintptr_t) mmap_min_addr, buffer_size, 00231 PROT_READ | PROT_EXEC | PROT_WRITE, 00232 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 00233 -1, 0) 00234 != MAP_FAILED) 00235 set_trampoline_buffer_space (mmap_min_addr, buffer_end, NULL); 00236 else 00237 { 00238 snprintf (buf, IPA_BUFSIZ, "low-64K-buffer mmap() failed: %s", 00239 strerror (errno)); 00240 set_trampoline_buffer_space (0, 0, buf); 00241 } 00242 } 00243 else 00244 { 00245 snprintf (buf, IPA_BUFSIZ, "mmap_min_addr is %d, must be %d or less", 00246 (int) mmap_min_addr, (int) buffer_end - min_buffer_size); 00247 set_trampoline_buffer_space (0, 0, buf); 00248 } 00249 } 00250 00251 void 00252 initialize_low_tracepoint (void) 00253 { 00254 init_registers_i386_linux (); 00255 ipa_tdesc = tdesc_i386_linux; 00256 initialize_fast_tracepoint_trampoline_buffer (); 00257 }