| OLD | NEW |
| 1 /* GNU/Linux on ARM target support. | 1 /* GNU/Linux on ARM target support. |
| 2 | 2 |
| 3 Copyright (C) 1999-2012 Free Software Foundation, Inc. | 3 Copyright (C) 1999-2012 Free Software Foundation, Inc. |
| 4 | 4 |
| 5 This file is part of GDB. | 5 This file is part of GDB. |
| 6 | 6 |
| 7 This program is free software; you can redistribute it and/or modify | 7 This program is free software; you can redistribute it and/or modify |
| 8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
| 9 the Free Software Foundation; either version 3 of the License, or | 9 the Free Software Foundation; either version 3 of the License, or |
| 10 (at your option) any later version. | 10 (at your option) any later version. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 #include "arm-tdep.h" | 37 #include "arm-tdep.h" |
| 38 #include "arm-linux-tdep.h" | 38 #include "arm-linux-tdep.h" |
| 39 #include "linux-tdep.h" | 39 #include "linux-tdep.h" |
| 40 #include "glibc-tdep.h" | 40 #include "glibc-tdep.h" |
| 41 #include "arch-utils.h" | 41 #include "arch-utils.h" |
| 42 #include "inferior.h" | 42 #include "inferior.h" |
| 43 #include "gdbthread.h" | 43 #include "gdbthread.h" |
| 44 #include "symfile.h" | 44 #include "symfile.h" |
| 45 | 45 |
| 46 #include "cli/cli-utils.h" |
| 47 #include "stap-probe.h" |
| 48 #include "parser-defs.h" |
| 49 #include "user-regs.h" |
| 50 #include <ctype.h> |
| 51 |
| 46 #include "gdb_string.h" | 52 #include "gdb_string.h" |
| 47 | 53 |
| 48 /* This is defined in <elf.h> on ARM GNU/Linux systems. */ | 54 /* This is defined in <elf.h> on ARM GNU/Linux systems. */ |
| 49 #define AT_HWCAP 16 | 55 #define AT_HWCAP 16 |
| 50 | 56 |
| 51 extern int arm_apcs_32; | 57 extern int arm_apcs_32; |
| 52 | 58 |
| 53 /* Under ARM GNU/Linux the traditional way of performing a breakpoint | 59 /* Under ARM GNU/Linux the traditional way of performing a breakpoint |
| 54 is to execute a particular software interrupt, rather than use a | 60 is to execute a particular software interrupt, rather than use a |
| 55 particular undefined instruction to provoke a trap. Upon exection | 61 particular undefined instruction to provoke a trap. Upon exection |
| (...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 sal.explicit_pc = 1; | 936 sal.explicit_pc = 1; |
| 931 | 937 |
| 932 frame = get_prev_frame (frame); | 938 frame = get_prev_frame (frame); |
| 933 | 939 |
| 934 if (frame) | 940 if (frame) |
| 935 { | 941 { |
| 936 inferior_thread ()->control.step_resume_breakpoint | 942 inferior_thread ()->control.step_resume_breakpoint |
| 937 = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame), | 943 = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame), |
| 938 bp_step_resume); | 944 bp_step_resume); |
| 939 | 945 |
| 946 /* set_momentary_breakpoint invalidates FRAME. */ |
| 947 frame = NULL; |
| 948 |
| 940 /* We need to make sure we actually insert the momentary | 949 /* We need to make sure we actually insert the momentary |
| 941 breakpoint set above. */ | 950 breakpoint set above. */ |
| 942 insert_breakpoints (); | 951 insert_breakpoints (); |
| 943 } | 952 } |
| 944 else if (debug_displaced) | 953 else if (debug_displaced) |
| 945 fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous " | 954 fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous " |
| 946 "frame to set momentary breakpoint for " | 955 "frame to set momentary breakpoint for " |
| 947 "sigreturn/rt_sigreturn\n"); | 956 "sigreturn/rt_sigreturn\n"); |
| 948 } | 957 } |
| 949 else if (debug_displaced) | 958 else if (debug_displaced) |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 dsc->u.svc.copy_svc_os = arm_linux_copy_svc; | 1055 dsc->u.svc.copy_svc_os = arm_linux_copy_svc; |
| 1047 | 1056 |
| 1048 arm_process_displaced_insn (gdbarch, from, to, regs, dsc); | 1057 arm_process_displaced_insn (gdbarch, from, to, regs, dsc); |
| 1049 } | 1058 } |
| 1050 | 1059 |
| 1051 arm_displaced_init_closure (gdbarch, from, to, dsc); | 1060 arm_displaced_init_closure (gdbarch, from, to, dsc); |
| 1052 | 1061 |
| 1053 return dsc; | 1062 return dsc; |
| 1054 } | 1063 } |
| 1055 | 1064 |
| 1065 static int |
| 1066 arm_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) |
| 1067 { |
| 1068 return (*s == '#' /* Literal number. */ |
| 1069 || *s == '[' /* Register indirection or |
| 1070 displacement. */ |
| 1071 || isalpha (*s)); /* Register value. */ |
| 1072 } |
| 1073 |
| 1074 /* This routine is used to parse a special token in ARM's assembly. |
| 1075 |
| 1076 The special tokens parsed by it are: |
| 1077 |
| 1078 - Register displacement (e.g, [fp, #-8]) |
| 1079 |
| 1080 It returns one if the special token has been parsed successfully, |
| 1081 or zero if the current token is not considered special. */ |
| 1082 |
| 1083 static int |
| 1084 arm_stap_parse_special_token (struct gdbarch *gdbarch, |
| 1085 struct stap_parse_info *p) |
| 1086 { |
| 1087 if (*p->arg == '[') |
| 1088 { |
| 1089 /* Temporary holder for lookahead. */ |
| 1090 const char *tmp = p->arg; |
| 1091 /* Used to save the register name. */ |
| 1092 const char *start; |
| 1093 char *regname; |
| 1094 int len, offset; |
| 1095 int got_minus = 0; |
| 1096 long displacement; |
| 1097 struct stoken str; |
| 1098 |
| 1099 ++tmp; |
| 1100 start = tmp; |
| 1101 |
| 1102 /* Register name. */ |
| 1103 while (isalnum (*tmp)) |
| 1104 ++tmp; |
| 1105 |
| 1106 if (*tmp != ',') |
| 1107 return 0; |
| 1108 |
| 1109 len = tmp - start; |
| 1110 regname = alloca (len + 2); |
| 1111 |
| 1112 offset = 0; |
| 1113 if (isdigit (*start)) |
| 1114 { |
| 1115 /* If we are dealing with a register whose name begins with a |
| 1116 digit, it means we should prefix the name with the letter |
| 1117 `r', because GDB expects this name pattern. Otherwise (e.g., |
| 1118 we are dealing with the register `fp'), we don't need to |
| 1119 add such a prefix. */ |
| 1120 regname[0] = 'r'; |
| 1121 offset = 1; |
| 1122 } |
| 1123 |
| 1124 strncpy (regname + offset, start, len); |
| 1125 len += offset; |
| 1126 regname[len] = '\0'; |
| 1127 |
| 1128 if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) |
| 1129 error (_("Invalid register name `%s' on expression `%s'."), |
| 1130 regname, p->saved_arg); |
| 1131 |
| 1132 ++tmp; |
| 1133 tmp = skip_spaces_const (tmp); |
| 1134 if (*tmp++ != '#') |
| 1135 return 0; |
| 1136 |
| 1137 if (*tmp == '-') |
| 1138 { |
| 1139 ++tmp; |
| 1140 got_minus = 1; |
| 1141 } |
| 1142 |
| 1143 displacement = strtol (tmp, (char **) &tmp, 10); |
| 1144 |
| 1145 /* Skipping last `]'. */ |
| 1146 if (*tmp++ != ']') |
| 1147 return 0; |
| 1148 |
| 1149 /* The displacement. */ |
| 1150 write_exp_elt_opcode (OP_LONG); |
| 1151 write_exp_elt_type (builtin_type (gdbarch)->builtin_long); |
| 1152 write_exp_elt_longcst (displacement); |
| 1153 write_exp_elt_opcode (OP_LONG); |
| 1154 if (got_minus) |
| 1155 write_exp_elt_opcode (UNOP_NEG); |
| 1156 |
| 1157 /* The register name. */ |
| 1158 write_exp_elt_opcode (OP_REGISTER); |
| 1159 str.ptr = regname; |
| 1160 str.length = len; |
| 1161 write_exp_string (str); |
| 1162 write_exp_elt_opcode (OP_REGISTER); |
| 1163 |
| 1164 write_exp_elt_opcode (BINOP_ADD); |
| 1165 |
| 1166 /* Casting to the expected type. */ |
| 1167 write_exp_elt_opcode (UNOP_CAST); |
| 1168 write_exp_elt_type (lookup_pointer_type (p->arg_type)); |
| 1169 write_exp_elt_opcode (UNOP_CAST); |
| 1170 |
| 1171 write_exp_elt_opcode (UNOP_IND); |
| 1172 |
| 1173 p->arg = tmp; |
| 1174 } |
| 1175 else |
| 1176 return 0; |
| 1177 |
| 1178 return 1; |
| 1179 } |
| 1180 |
| 1056 static void | 1181 static void |
| 1057 arm_linux_init_abi (struct gdbarch_info info, | 1182 arm_linux_init_abi (struct gdbarch_info info, |
| 1058 struct gdbarch *gdbarch) | 1183 struct gdbarch *gdbarch) |
| 1059 { | 1184 { |
| 1060 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | 1185 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
| 1061 | 1186 |
| 1062 linux_init_abi (info, gdbarch); | 1187 linux_init_abi (info, gdbarch); |
| 1063 | 1188 |
| 1064 tdep->lowest_pc = 0x8000; | 1189 tdep->lowest_pc = 0x8000; |
| 1065 if (info.byte_order == BFD_ENDIAN_BIG) | 1190 if (info.byte_order == BFD_ENDIAN_BIG) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1145 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); | 1270 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); |
| 1146 | 1271 |
| 1147 /* Displaced stepping. */ | 1272 /* Displaced stepping. */ |
| 1148 set_gdbarch_displaced_step_copy_insn (gdbarch, | 1273 set_gdbarch_displaced_step_copy_insn (gdbarch, |
| 1149 arm_linux_displaced_step_copy_insn); | 1274 arm_linux_displaced_step_copy_insn); |
| 1150 set_gdbarch_displaced_step_fixup (gdbarch, arm_displaced_step_fixup); | 1275 set_gdbarch_displaced_step_fixup (gdbarch, arm_displaced_step_fixup); |
| 1151 set_gdbarch_displaced_step_free_closure (gdbarch, | 1276 set_gdbarch_displaced_step_free_closure (gdbarch, |
| 1152 simple_displaced_step_free_closure); | 1277 simple_displaced_step_free_closure); |
| 1153 set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point); | 1278 set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point); |
| 1154 | 1279 |
| 1280 /* Reversible debugging, process record. */ |
| 1281 set_gdbarch_process_record (gdbarch, arm_process_record); |
| 1282 |
| 1283 /* SystemTap functions. */ |
| 1284 set_gdbarch_stap_integer_prefix (gdbarch, "#"); |
| 1285 set_gdbarch_stap_register_prefix (gdbarch, "r"); |
| 1286 set_gdbarch_stap_register_indirection_prefix (gdbarch, "["); |
| 1287 set_gdbarch_stap_register_indirection_suffix (gdbarch, "]"); |
| 1288 set_gdbarch_stap_gdb_register_prefix (gdbarch, "r"); |
| 1289 set_gdbarch_stap_is_single_operand (gdbarch, arm_stap_is_single_operand); |
| 1290 set_gdbarch_stap_parse_special_token (gdbarch, |
| 1291 arm_stap_parse_special_token); |
| 1155 | 1292 |
| 1156 tdep->syscall_next_pc = arm_linux_syscall_next_pc; | 1293 tdep->syscall_next_pc = arm_linux_syscall_next_pc; |
| 1294 |
| 1295 /* Syscall record. */ |
| 1296 tdep->arm_swi_record = NULL; |
| 1157 } | 1297 } |
| 1158 | 1298 |
| 1159 /* Provide a prototype to silence -Wmissing-prototypes. */ | 1299 /* Provide a prototype to silence -Wmissing-prototypes. */ |
| 1160 extern initialize_file_ftype _initialize_arm_linux_tdep; | 1300 extern initialize_file_ftype _initialize_arm_linux_tdep; |
| 1161 | 1301 |
| 1162 void | 1302 void |
| 1163 _initialize_arm_linux_tdep (void) | 1303 _initialize_arm_linux_tdep (void) |
| 1164 { | 1304 { |
| 1165 gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX, | 1305 gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX, |
| 1166 arm_linux_init_abi); | 1306 arm_linux_init_abi); |
| 1167 } | 1307 } |
| OLD | NEW |