i386-netbsd-tdep.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /* Target-dependent code for NetBSD/i386.
  2. Copyright (C) 1988-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include "defs.h"
  15. #include "arch-utils.h"
  16. #include "frame.h"
  17. #include "gdbcore.h"
  18. #include "regcache.h"
  19. #include "regset.h"
  20. #include "osabi.h"
  21. #include "symtab.h"
  22. #include "trad-frame.h"
  23. #include "tramp-frame.h"
  24. #include "i386-tdep.h"
  25. #include "i387-tdep.h"
  26. #include "netbsd-tdep.h"
  27. #include "solib-svr4.h"
  28. /* From <machine/reg.h>. */
  29. static int i386nbsd_r_reg_offset[] =
  30. {
  31. 0 * 4, /* %eax */
  32. 1 * 4, /* %ecx */
  33. 2 * 4, /* %edx */
  34. 3 * 4, /* %ebx */
  35. 4 * 4, /* %esp */
  36. 5 * 4, /* %ebp */
  37. 6 * 4, /* %esi */
  38. 7 * 4, /* %edi */
  39. 8 * 4, /* %eip */
  40. 9 * 4, /* %eflags */
  41. 10 * 4, /* %cs */
  42. 11 * 4, /* %ss */
  43. 12 * 4, /* %ds */
  44. 13 * 4, /* %es */
  45. 14 * 4, /* %fs */
  46. 15 * 4 /* %gs */
  47. };
  48. /* From <machine/signal.h>. */
  49. static int i386nbsd_sc_reg_offset[] =
  50. {
  51. 10 * 4, /* %eax */
  52. 9 * 4, /* %ecx */
  53. 8 * 4, /* %edx */
  54. 7 * 4, /* %ebx */
  55. 14 * 4, /* %esp */
  56. 6 * 4, /* %ebp */
  57. 5 * 4, /* %esi */
  58. 4 * 4, /* %edi */
  59. 11 * 4, /* %eip */
  60. 13 * 4, /* %eflags */
  61. 12 * 4, /* %cs */
  62. 15 * 4, /* %ss */
  63. 3 * 4, /* %ds */
  64. 2 * 4, /* %es */
  65. 1 * 4, /* %fs */
  66. 0 * 4 /* %gs */
  67. };
  68. /* From <machine/mcontext.h>. */
  69. static int i386nbsd_mc_reg_offset[] =
  70. {
  71. 11 * 4, /* %eax */
  72. 10 * 4, /* %ecx */
  73. 9 * 4, /* %edx */
  74. 8 * 4, /* %ebx */
  75. 7 * 4, /* %esp */
  76. 6 * 4, /* %ebp */
  77. 5 * 4, /* %esi */
  78. 4 * 4, /* %edi */
  79. 14 * 4, /* %eip */
  80. 16 * 4, /* %eflags */
  81. 15 * 4, /* %cs */
  82. 18 * 4, /* %ss */
  83. 3 * 4, /* %ds */
  84. 2 * 4, /* %es */
  85. 1 * 4, /* %fs */
  86. 0 * 4 /* %gs */
  87. };
  88. static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
  89. struct frame_info *,
  90. struct trad_frame_cache *,
  91. CORE_ADDR);
  92. static const struct tramp_frame i386nbsd_sigtramp_sc16 =
  93. {
  94. SIGTRAMP_FRAME,
  95. 1,
  96. {
  97. /* leal 0x10(%esp), %eax */
  98. { 0x8d, ULONGEST_MAX },
  99. { 0x44, ULONGEST_MAX },
  100. { 0x24, ULONGEST_MAX },
  101. { 0x10, ULONGEST_MAX },
  102. /* pushl %eax */
  103. { 0x50, ULONGEST_MAX },
  104. /* pushl %eax */
  105. { 0x50, ULONGEST_MAX },
  106. /* movl $0x127, %eax # __sigreturn14 */
  107. { 0xb8, ULONGEST_MAX },
  108. { 0x27, ULONGEST_MAX },
  109. {0x01, ULONGEST_MAX },
  110. {0x00, ULONGEST_MAX },
  111. {0x00, ULONGEST_MAX },
  112. /* int $0x80 */
  113. { 0xcd, ULONGEST_MAX },
  114. { 0x80, ULONGEST_MAX},
  115. /* movl $0x1, %eax # exit */
  116. { 0xb8, ULONGEST_MAX },
  117. { 0x01, ULONGEST_MAX },
  118. {0x00, ULONGEST_MAX },
  119. {0x00, ULONGEST_MAX },
  120. {0x00, ULONGEST_MAX },
  121. /* int $0x80 */
  122. { 0xcd, ULONGEST_MAX },
  123. { 0x80, ULONGEST_MAX},
  124. { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
  125. },
  126. i386nbsd_sigtramp_cache_init
  127. };
  128. static const struct tramp_frame i386nbsd_sigtramp_sc2 =
  129. {
  130. SIGTRAMP_FRAME,
  131. 1,
  132. {
  133. /* leal 0x0c(%esp), %eax */
  134. { 0x8d, ULONGEST_MAX },
  135. { 0x44, ULONGEST_MAX },
  136. { 0x24, ULONGEST_MAX },
  137. { 0x0c, ULONGEST_MAX },
  138. /* movl %eax, 0x4(%esp) */
  139. { 0x89, ULONGEST_MAX },
  140. { 0x44, ULONGEST_MAX },
  141. { 0x24, ULONGEST_MAX },
  142. { 0x04, ULONGEST_MAX },
  143. /* movl $0x127, %eax # __sigreturn14 */
  144. { 0xb8, ULONGEST_MAX },
  145. { 0x27, ULONGEST_MAX },
  146. {0x01, ULONGEST_MAX },
  147. {0x00, ULONGEST_MAX },
  148. {0x00, ULONGEST_MAX },
  149. /* int $0x80 */
  150. { 0xcd, ULONGEST_MAX },
  151. { 0x80, ULONGEST_MAX},
  152. /* movl %eax, 0x4(%esp) */
  153. { 0x89, ULONGEST_MAX },
  154. { 0x44, ULONGEST_MAX },
  155. { 0x24, ULONGEST_MAX },
  156. { 0x04, ULONGEST_MAX },
  157. /* movl $0x1, %eax */
  158. { 0xb8, ULONGEST_MAX },
  159. { 0x01, ULONGEST_MAX },
  160. {0x00, ULONGEST_MAX },
  161. {0x00, ULONGEST_MAX },
  162. {0x00, ULONGEST_MAX },
  163. /* int $0x80 */
  164. { 0xcd, ULONGEST_MAX },
  165. { 0x80, ULONGEST_MAX},
  166. { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
  167. },
  168. i386nbsd_sigtramp_cache_init
  169. };
  170. static const struct tramp_frame i386nbsd_sigtramp_si2 =
  171. {
  172. SIGTRAMP_FRAME,
  173. 1,
  174. {
  175. /* movl 8(%esp),%eax */
  176. { 0x8b, ULONGEST_MAX },
  177. { 0x44, ULONGEST_MAX },
  178. { 0x24, ULONGEST_MAX },
  179. { 0x08, ULONGEST_MAX },
  180. /* movl %eax, 0x4(%esp) */
  181. { 0x89, ULONGEST_MAX },
  182. { 0x44, ULONGEST_MAX },
  183. { 0x24, ULONGEST_MAX },
  184. { 0x04, ULONGEST_MAX },
  185. /* movl $0x134, %eax # setcontext */
  186. { 0xb8, ULONGEST_MAX },
  187. { 0x34, ULONGEST_MAX },
  188. { 0x01, ULONGEST_MAX },
  189. { 0x00, ULONGEST_MAX },
  190. { 0x00, ULONGEST_MAX },
  191. /* int $0x80 */
  192. { 0xcd, ULONGEST_MAX },
  193. { 0x80, ULONGEST_MAX },
  194. /* movl %eax, 0x4(%esp) */
  195. { 0x89, ULONGEST_MAX },
  196. { 0x44, ULONGEST_MAX },
  197. { 0x24, ULONGEST_MAX },
  198. { 0x04, ULONGEST_MAX },
  199. /* movl $0x1, %eax */
  200. { 0xb8, ULONGEST_MAX },
  201. { 0x01, ULONGEST_MAX },
  202. { 0x00, ULONGEST_MAX },
  203. { 0x00, ULONGEST_MAX },
  204. { 0x00, ULONGEST_MAX },
  205. /* int $0x80 */
  206. { 0xcd, ULONGEST_MAX },
  207. { 0x80, ULONGEST_MAX },
  208. { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
  209. },
  210. i386nbsd_sigtramp_cache_init
  211. };
  212. static const struct tramp_frame i386nbsd_sigtramp_si31 =
  213. {
  214. SIGTRAMP_FRAME,
  215. 1,
  216. {
  217. /* leal 0x8c(%esp), %eax */
  218. { 0x8d, ULONGEST_MAX },
  219. { 0x84, ULONGEST_MAX },
  220. { 0x24, ULONGEST_MAX },
  221. { 0x8c, ULONGEST_MAX },
  222. { 0x00, ULONGEST_MAX },
  223. { 0x00, ULONGEST_MAX },
  224. { 0x00, ULONGEST_MAX },
  225. /* movl %eax, 0x4(%esp) */
  226. { 0x89, ULONGEST_MAX },
  227. { 0x44, ULONGEST_MAX },
  228. { 0x24, ULONGEST_MAX },
  229. { 0x04, ULONGEST_MAX },
  230. /* movl $0x134, %eax # setcontext */
  231. { 0xb8, ULONGEST_MAX },
  232. { 0x34, ULONGEST_MAX },
  233. { 0x01, ULONGEST_MAX },
  234. { 0x00, ULONGEST_MAX },
  235. { 0x00, ULONGEST_MAX },
  236. /* int $0x80 */
  237. { 0xcd, ULONGEST_MAX },
  238. { 0x80, ULONGEST_MAX},
  239. /* movl %eax, 0x4(%esp) */
  240. { 0x89, ULONGEST_MAX },
  241. { 0x44, ULONGEST_MAX },
  242. { 0x24, ULONGEST_MAX },
  243. { 0x04, ULONGEST_MAX },
  244. /* movl $0x1, %eax */
  245. { 0xb8, ULONGEST_MAX },
  246. { 0x01, ULONGEST_MAX },
  247. {0x00, ULONGEST_MAX },
  248. {0x00, ULONGEST_MAX },
  249. {0x00, ULONGEST_MAX },
  250. /* int $0x80 */
  251. { 0xcd, ULONGEST_MAX },
  252. { 0x80, ULONGEST_MAX},
  253. { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
  254. },
  255. i386nbsd_sigtramp_cache_init
  256. };
  257. static const struct tramp_frame i386nbsd_sigtramp_si4 =
  258. {
  259. SIGTRAMP_FRAME,
  260. 1,
  261. {
  262. /* leal 0x8c(%esp), %eax */
  263. { 0x8d, ULONGEST_MAX },
  264. { 0x84, ULONGEST_MAX },
  265. { 0x24, ULONGEST_MAX },
  266. { 0x8c, ULONGEST_MAX },
  267. { 0x00, ULONGEST_MAX },
  268. { 0x00, ULONGEST_MAX },
  269. { 0x00, ULONGEST_MAX },
  270. /* movl %eax, 0x4(%esp) */
  271. { 0x89, ULONGEST_MAX },
  272. { 0x44, ULONGEST_MAX },
  273. { 0x24, ULONGEST_MAX },
  274. { 0x04, ULONGEST_MAX },
  275. /* movl $0x134, %eax # setcontext */
  276. { 0xb8, ULONGEST_MAX },
  277. { 0x34, ULONGEST_MAX },
  278. { 0x01, ULONGEST_MAX },
  279. { 0x00, ULONGEST_MAX },
  280. { 0x00, ULONGEST_MAX },
  281. /* int $0x80 */
  282. { 0xcd, ULONGEST_MAX },
  283. { 0x80, ULONGEST_MAX},
  284. /* movl $0xffffffff,0x4(%esp) */
  285. { 0xc7, ULONGEST_MAX },
  286. { 0x44, ULONGEST_MAX },
  287. { 0x24, ULONGEST_MAX },
  288. { 0x04, ULONGEST_MAX },
  289. { 0xff, ULONGEST_MAX },
  290. { 0xff, ULONGEST_MAX },
  291. { 0xff, ULONGEST_MAX },
  292. { 0xff, ULONGEST_MAX },
  293. /* movl $0x1, %eax */
  294. { 0xb8, ULONGEST_MAX },
  295. { 0x01, ULONGEST_MAX },
  296. {0x00, ULONGEST_MAX },
  297. {0x00, ULONGEST_MAX },
  298. {0x00, ULONGEST_MAX },
  299. /* int $0x80 */
  300. { 0xcd, ULONGEST_MAX },
  301. { 0x80, ULONGEST_MAX},
  302. { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
  303. },
  304. i386nbsd_sigtramp_cache_init
  305. };
  306. static void
  307. i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
  308. struct frame_info *this_frame,
  309. struct trad_frame_cache *this_cache,
  310. CORE_ADDR func)
  311. {
  312. struct gdbarch *gdbarch = get_frame_arch (this_frame);
  313. enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  314. CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
  315. CORE_ADDR base;
  316. int *reg_offset;
  317. int num_regs;
  318. int i;
  319. if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
  320. {
  321. reg_offset = i386nbsd_sc_reg_offset;
  322. num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
  323. /* Read in the sigcontext address. */
  324. base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
  325. }
  326. else
  327. {
  328. reg_offset = i386nbsd_mc_reg_offset;
  329. num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
  330. /* Read in the ucontext address. */
  331. base = read_memory_unsigned_integer (sp + 8, 4, byte_order);
  332. /* offsetof(ucontext_t, uc_mcontext) == 36 */
  333. base += 36;
  334. }
  335. for (i = 0; i < num_regs; i++)
  336. if (reg_offset[i] != -1)
  337. trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
  338. /* Construct the frame ID using the function start. */
  339. trad_frame_set_id (this_cache, frame_id_build (sp, func));
  340. }
  341. static void
  342. i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  343. {
  344. i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
  345. /* Obviously NetBSD is BSD-based. */
  346. i386bsd_init_abi (info, gdbarch);
  347. nbsd_init_abi (info, gdbarch);
  348. /* NetBSD has a different `struct reg'. */
  349. tdep->gregset_reg_offset = i386nbsd_r_reg_offset;
  350. tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
  351. tdep->sizeof_gregset = 16 * 4;
  352. /* NetBSD uses -freg-struct-return by default. */
  353. tdep->struct_return = reg_struct_return;
  354. /* NetBSD uses tramp_frame sniffers for signal trampolines. */
  355. tdep->sigcontext_addr= 0;
  356. tdep->sigtramp_start = 0;
  357. tdep->sigtramp_end = 0;
  358. tdep->sigtramp_p = 0;
  359. tdep->sc_reg_offset = 0;
  360. tdep->sc_num_regs = 0;
  361. tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
  362. tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
  363. tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
  364. tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
  365. tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
  366. }
  367. /* NetBSD ELF. */
  368. static void
  369. i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  370. {
  371. i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
  372. /* It's still NetBSD. */
  373. i386nbsd_init_abi (info, gdbarch);
  374. /* But ELF-based. */
  375. i386_elf_init_abi (info, gdbarch);
  376. /* NetBSD ELF uses SVR4-style shared libraries. */
  377. set_solib_svr4_fetch_link_map_offsets
  378. (gdbarch, svr4_ilp32_fetch_link_map_offsets);
  379. /* NetBSD ELF uses -fpcc-struct-return by default. */
  380. tdep->struct_return = pcc_struct_return;
  381. }
  382. void _initialize_i386nbsd_tdep ();
  383. void
  384. _initialize_i386nbsd_tdep ()
  385. {
  386. gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD,
  387. i386nbsdelf_init_abi);
  388. }