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 |