1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Target operations for the remote server for GDB.
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2002, 2004, 2005, 2011
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Free Software Foundation, Inc.
4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Contributed by MontaVista Software.
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This file is part of GDB.
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   It has been modified to integrate it in valgrind
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This program is free software; you can redistribute it and/or modify
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   it under the terms of the GNU General Public License as published by
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   the Free Software Foundation; either version 2 of the License, or
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (at your option) any later version.
14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This program is distributed in the hope that it will be useful,
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   but WITHOUT ANY WARRANTY; without even the implied warranty of
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   GNU General Public License for more details.
19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   You should have received a copy of the GNU General Public License
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   along with this program; if not, write to the Free Software
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Foundation, Inc., 51 Franklin Street, Fifth Floor,
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Boston, MA 02110-1301, USA.  */
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "server.h"
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "target.h"
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "regdef.h"
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "regcache.h"
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "valgrind_low.h"
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "gdb/signals.h"
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_aspacemgr.h"
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_machine.h"
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_threadstate.h"
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_transtab.h"
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_gdbserver.h"
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_debuginfo.h"
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* the_low_target defines the architecture specific aspects depending
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   on the cpu */
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic struct valgrind_target_ops the_low_target;
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengchar *image_ptid(unsigned long ptid)
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  static char result[100];
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  VG_(sprintf) (result, "id %ld", ptid);
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  return result;
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define get_thread(inf) ((struct thread_info *)(inf))
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid remove_thread_if_not_in_vg_threads (struct inferior_list_entry *inf)
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  struct thread_info *thread = get_thread (inf);
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  if (!VG_(lwpid_to_vgtid)(thread_to_gdb_id(thread))) {
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     dlog(1, "removing gdb ptid %s\n",
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          image_ptid(thread_to_gdb_id(thread)));
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     remove_thread (thread);
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* synchronize threads known by valgrind and threads known by gdbserver */
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid valgrind_update_threads (int pid)
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  ThreadId tid;
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  ThreadState *ts;
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  unsigned long ptid;
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  struct thread_info *ti;
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  /* call remove_thread for all gdb threads not in valgrind threads */
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  for_each_inferior (&all_threads, remove_thread_if_not_in_vg_threads);
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  /* call add_thread for all valgrind threads not known in gdb all_threads */
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  for (tid = 1; tid < VG_N_THREADS; tid++) {
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define LOCAL_THREAD_TRACE " ti* %p vgtid %d status %s as gdb ptid %s lwpid %d\n", \
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ti, tid, VG_(name_of_ThreadStatus) (ts->status), \
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        image_ptid (ptid), ts->os_state.lwpid
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (VG_(is_valid_tid) (tid)) {
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ts = VG_(get_ThreadState) (tid);
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ptid = ts->os_state.lwpid;
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        ti = gdb_id_to_thread (ptid);
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (!ti) {
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           /* we do not report the threads which are not yet fully
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              initialized otherwise this creates duplicated threads
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              in gdb: once with pid xxx lwpid 0, then after that
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              with pid xxx lwpid yyy. */
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (ts->status != VgTs_Init) {
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              dlog(1, "adding_thread" LOCAL_THREAD_TRACE);
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              add_thread (ptid, ts, ptid);
93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           }
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        } else {
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           dlog(2, "(known thread)" LOCAL_THREAD_TRACE);
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#undef LOCAL_THREAD_TRACE
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstruct reg* build_shadow_arch (struct reg *reg_defs, int n) {
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i, r;
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static const char *postfix[3] = { "", "s1", "s2" };
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   struct reg *new_regs = malloc(3 * n * sizeof(reg_defs[0]));
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int reg_set_len = reg_defs[n-1].offset + reg_defs[n-1].size;
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 3; i++) {
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (r = 0; r < n; r++) {
111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         char *regname = malloc(strlen(reg_defs[r].name)
112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                + strlen (postfix[i]) + 1);
113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         strcpy (regname, reg_defs[r].name);
114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         strcat (regname, postfix[i]);
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         new_regs[i*n + r].name = regname;
116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         new_regs[i*n + r].offset = i*reg_set_len + reg_defs[r].offset;
117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         new_regs[i*n + r].size = reg_defs[r].size;
118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dlog(1,
119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              "%10s Nr %d offset(bit) %d offset(byte) %d  size(bit) %d\n",
120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              new_regs[i*n + r].name, i*n + r, new_regs[i*n + r].offset,
121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              (new_regs[i*n + r].offset) / 8, new_regs[i*n + r].size);
122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return new_regs;
126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic CORE_ADDR stopped_data_address = 0;
130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid VG_(set_watchpoint_stop_address) (Addr addr)
131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stopped_data_address = addr;
133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_stopped_by_watchpoint (void)
136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return stopped_data_address != 0;
138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
140663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengCORE_ADDR valgrind_stopped_data_address (void)
141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return stopped_data_address;
143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* pc at which we last stopped */
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic CORE_ADDR stop_pc;
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* pc at which we resume.
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   If stop_pc != resume_pc, it means
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      gdb/gdbserver has changed the pc so as to have either
151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      a    "continue by jumping at that address"
152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      or a "continue at that address to call some code from gdb".
153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic CORE_ADDR resume_pc;
155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic int vki_signal_to_report;
157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid gdbserver_signal_encountered (Int vki_sigNo)
159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vki_signal_to_report = vki_sigNo;
161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic int vki_signal_to_deliver;
164663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengBool gdbserver_deliver_signal (Int vki_sigNo)
165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return vki_sigNo == vki_signal_to_deliver;
167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic unsigned char exit_status_to_report;
170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int exit_code_to_report;
171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid gdbserver_process_exit_encountered (unsigned char status, Int code)
172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vg_assert (status == 'W' || status == 'X');
174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   exit_status_to_report = status;
175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   exit_code_to_report = code;
176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengchar* sym (Addr addr)
180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   static char buf[200];
182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   VG_(describe_IP) (addr, buf, 200);
183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return buf;
184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
186663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengThreadId vgdb_interrupted_tid = 0;
187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 0 => not single stepping.
189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   1 => single stepping asked by gdb
190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   2 => single stepping asked by valgrind (watchpoint) */
191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic int stepping = 0;
192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
193663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAddr valgrind_get_ignore_break_once(void)
194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (valgrind_single_stepping())
196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return resume_pc;
197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return 0;
199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid valgrind_set_single_stepping(Bool set)
202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (set)
204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stepping = 2;
205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stepping = 0;
207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
209663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengBool valgrind_single_stepping(void)
210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (stepping)
212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return True;
213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return False;
215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_thread_alive (unsigned long tid)
218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  struct thread_info *ti =  gdb_id_to_thread(tid);
220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  ThreadState *tst;
221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  if (ti != NULL) {
223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     tst = (ThreadState *) inferior_target_data (ti);
224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     return tst->status != VgTs_Zombie;
225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  else {
227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    return 0;
228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid valgrind_resume (struct thread_resume *resume_info)
232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dlog(1,
234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        "resume_info step %d sig %d stepping %d\n",
235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        resume_info->step,
236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        resume_info->sig,
237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        stepping);
238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (valgrind_stopped_by_watchpoint()) {
239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dlog(1, "clearing watchpoint stopped_data_address %p\n",
240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           C2v(stopped_data_address));
241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(set_watchpoint_stop_address) ((Addr) 0);
242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vki_signal_to_deliver = resume_info->sig;
244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stepping = resume_info->step;
246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   resume_pc = (*the_low_target.get_pc) ();
247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (resume_pc != stop_pc) {
248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dlog(1,
249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           "stop_pc %p changed to be resume_pc %s\n",
250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           C2v(stop_pc), sym(resume_pc));
251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regcache_invalidate();
253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengunsigned char valgrind_wait (char *ourstatus)
256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int pid;
258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   unsigned long wptid;
259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ThreadState *tst;
260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   enum target_signal sig;
261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int code;
262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   pid = VG_(getpid) ();
264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dlog(1, "enter valgrind_wait pid %d\n", pid);
265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regcache_invalidate();
267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   valgrind_update_threads(pid);
268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* First see if we are done with this process. */
270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (exit_status_to_report != 0) {
271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      *ourstatus = exit_status_to_report;
272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      exit_status_to_report = 0;
273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (*ourstatus == 'W') {
275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         code = exit_code_to_report;
276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         exit_code_to_report = 0;
277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         dlog(1, "exit valgrind_wait status W exit code %d\n", code);
278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return code;
279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (*ourstatus == 'X') {
282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         sig = target_signal_from_host(exit_code_to_report);
283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         exit_code_to_report = 0;
284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         dlog(1, "exit valgrind_wait status X signal %d\n", sig);
285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return sig;
286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* in valgrind, we consider that a wait always succeeds with STOPPED 'T'
290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      and with a signal TRAP (i.e. a breakpoint), unless there is
291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      a signal to report. */
292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *ourstatus = 'T';
293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vki_signal_to_report == 0)
294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sig = TARGET_SIGNAL_TRAP;
295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sig = target_signal_from_host(vki_signal_to_report);
297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vki_signal_to_report = 0;
298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vgdb_interrupted_tid != 0)
301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tst = VG_(get_ThreadState) (vgdb_interrupted_tid);
302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tst = VG_(get_ThreadState) (VG_(running_tid));
304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   wptid = tst->os_state.lwpid;
305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* we can only change the current_inferior when the wptid references
306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      an existing thread. Otherwise, we are still in the init phase.
307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (hack similar to main thread hack in valgrind_update_threads) */
308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (tst->os_state.lwpid)
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      current_inferior = gdb_id_to_thread (wptid);
310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stop_pc = (*the_low_target.get_pc) ();
311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dlog(1,
313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        "exit valgrind_wait status T ptid %s stop_pc %s signal %d\n",
314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        image_ptid (wptid), sym (stop_pc), sig);
315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return sig;
316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Fetch one register from valgrind VEX guest state.  */
319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid fetch_register (int regno)
321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int size;
323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ThreadState *tst = (ThreadState *) inferior_target_data (current_inferior);
324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ThreadId tid = tst->tid;
325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (regno >= the_low_target.num_regs) {
327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dlog(0, "error fetch_register regno %d max %d\n",
328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regno, the_low_target.num_regs);
329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   size = register_size (regno);
332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (size > 0) {
333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool mod;
334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      char buf [size];
335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(memset) (buf, 0, size); // registers not fetched will be seen as 0.
336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (*the_low_target.transfer_register) (tid, regno, buf,
337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           valgrind_to_gdbserver, size, &mod);
338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // Note: the *mod received from transfer_register is not interesting.
339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // We are interested to see if the register data in the register cache is modified.
340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      supply_register (regno, buf, &mod);
341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (mod && VG_(debugLog_getLevel)() > 1) {
342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         char bufimage [2*size + 1];
343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         heximage (bufimage, buf, size);
344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dlog(2, "fetched register %d size %d name %s value %s tid %d status %s\n",
345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              regno, size, the_low_target.reg_defs[regno].name, bufimage,
346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              tid, VG_(name_of_ThreadStatus) (tst->status));
347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Fetch all registers, or just one, from the child process.  */
352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid usr_fetch_inferior_registers (int regno)
354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (regno == -1 || regno == 0)
356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (regno = 0; regno < the_low_target.num_regs; regno++)
357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fetch_register (regno);
358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fetch_register (regno);
360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Store our register values back into the inferior.
363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   If REGNO is -1, do this for all registers.
364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Otherwise, REGNO specifies which register (so we can save time).  */
365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid usr_store_inferior_registers (int regno)
367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int size;
369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ThreadState *tst = (ThreadState *) inferior_target_data (current_inferior);
370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ThreadId tid = tst->tid;
371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (regno >= 0) {
373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (regno >= the_low_target.num_regs) {
375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dlog(0, "error store_register regno %d max %d\n",
376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              regno, the_low_target.num_regs);
377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      size = register_size (regno);
381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (size > 0) {
382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool mod;
383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Addr old_SP, new_SP;
384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         char buf[size];
385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (regno == the_low_target.stack_pointer_regno) {
387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* When the stack pointer register is changed such that
388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               the stack is extended, we better inform the tool of the
389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               stack increase.  This is needed in particular to avoid
390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               spurious Memcheck errors during Inferior calls. So, we
391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               save in old_SP the SP before the change. A change of
392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               stack pointer is also assumed to have initialised this
393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               new stack space. For the typical example of an inferior
394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               call, gdb writes arguments on the stack, and then
395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               changes the stack pointer. As the stack increase tool
396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               function might mark it as undefined, we have to call it
397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               at the good moment. */
398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            VG_(memset) ((void *) &old_SP, 0, size);
399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (*the_low_target.transfer_register) (tid, regno, (void *) &old_SP,
400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 valgrind_to_gdbserver, size, &mod);
401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         VG_(memset) (buf, 0, size);
404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         collect_register (regno, buf);
405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (*the_low_target.transfer_register) (tid, regno, buf,
406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              gdbserver_to_valgrind, size, &mod);
407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mod && VG_(debugLog_getLevel)() > 1) {
408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            char bufimage [2*size + 1];
409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            heximage (bufimage, buf, size);
410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dlog(2,
411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 "stored register %d size %d name %s value %s "
412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 "tid %d status %s\n",
413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 regno, size, the_low_target.reg_defs[regno].name, bufimage,
414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 tid, VG_(name_of_ThreadStatus) (tst->status));
415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (regno == the_low_target.stack_pointer_regno) {
417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            VG_(memcpy) (&new_SP, buf, size);
418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (old_SP > new_SP) {
419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               Word delta  = (Word)new_SP - (Word)old_SP;
420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dlog(1,
421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "   stack increase by stack pointer changed from %p to %p "
422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    "delta %ld\n",
423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    (void*) old_SP, (void *) new_SP,
424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    delta);
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               VG_TRACK( new_mem_stack_w_ECU, new_SP, -delta, 0 );
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               VG_TRACK( new_mem_stack,       new_SP, -delta );
427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               VG_TRACK( post_mem_write, Vg_CoreClientReq, tid,
428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         new_SP, -delta);
429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (regno = 0; regno < the_low_target.num_regs; regno++)
435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         usr_store_inferior_registers (regno);
436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid valgrind_fetch_registers (int regno)
440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   usr_fetch_inferior_registers (regno);
442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid valgrind_store_registers (int regno)
445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   usr_store_inferior_registers (regno);
447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
449eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy IvanovBool hostvisibility = False;
450eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov
451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   const void *sourceaddr = C2v (memaddr);
454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dlog(2, "reading memory %p size %d\n", sourceaddr, len);
455eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   if (VG_(am_is_valid_for_client) ((Addr) sourceaddr,
456eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                                    len, VKI_PROT_READ)
457eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov       || (hostvisibility
458eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov           && VG_(am_is_valid_for_valgrind) ((Addr) sourceaddr,
459eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                                             len, VKI_PROT_READ))) {
460eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      VG_(memcpy) (myaddr, sourceaddr, len);
461eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      return 0;
462eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   } else {
463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dlog(1, "error reading memory %p size %d\n", sourceaddr, len);
464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return -1;
465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
470eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   Bool is_valid_client_memory;
471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   void *targetaddr = C2v (memaddr);
472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dlog(2, "writing memory %p size %d\n", targetaddr, len);
473eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   is_valid_client_memory
474eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      = VG_(am_is_valid_for_client) ((Addr)targetaddr, len, VKI_PROT_WRITE);
475eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   if (is_valid_client_memory
476eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov       || (hostvisibility
477eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov           && VG_(am_is_valid_for_valgrind) ((Addr) targetaddr,
478eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                                             len, VKI_PROT_READ))) {
479eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      if (len > 0) {
480eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov         VG_(memcpy) (targetaddr, myaddr, len);
481eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov         if (is_valid_client_memory && VG_(tdict).track_post_mem_write) {
482eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov            /* Inform the tool of the post memwrite.  Note that we do the
483eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               minimum necessary to avoid complains from e.g.
484eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               memcheck. The idea is that the debugger is as least
485eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               intrusive as possible.  So, we do not inform of the pre
486eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               mem write (and in any case, this would cause problems with
487eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               memcheck that does not like our CorePart in
488eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               pre_mem_write. */
489eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov            ThreadState *tst =
490eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov               (ThreadState *) inferior_target_data (current_inferior);
491eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov            ThreadId tid = tst->tid;
492eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov            VG_(tdict).track_post_mem_write( Vg_CoreClientReq, tid,
493eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                                             (Addr) targetaddr, len );
494eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov         }
495eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      }
496eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      return 0;
497eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   } else {
498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dlog(1, "error writing memory %p size %d\n", targetaddr, len);
499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return -1;
500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* insert or remove a breakpoint */
504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_point (Bool insert, char type, CORE_ADDR addr, int len)
506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   PointKind kind;
508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (type) {
509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case '0': /* implemented by inserting checks at each instruction in sb */
510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      kind = software_breakpoint;
511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case '1': /* hw breakpoint, same implementation as sw breakpoint */
513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      kind = hardware_breakpoint;
514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case '2':
516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      kind = write_watchpoint;
517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case '3':
519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      kind = read_watchpoint;
520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case '4':
522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      kind = access_watchpoint;
523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vg_assert (0);
526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Attention: gdbserver convention differs: 0 means ok; 1 means not ok */
529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (VG_(gdbserver_point) (kind, insert, addr, len))
530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return 0;
531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return 1; /* error or unsupported */
533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst char* valgrind_target_xml (Bool shadow_mode)
536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return (*the_low_target.target_xml) (shadow_mode);
538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_insert_watchpoint (char type, CORE_ADDR addr, int len)
541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return valgrind_point (/* insert */ True, type, addr, len);
543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint valgrind_remove_watchpoint (char type, CORE_ADDR addr, int len)
546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return valgrind_point (/* insert*/ False, type, addr, len);
548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* returns a pointer to the architecture state corresponding to
551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the provided register set: 0 => normal guest registers,
552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              1 => shadow1
553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              2 => shadow2
554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
555663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengVexGuestArchState* get_arch (int set, ThreadState* tst)
556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  switch (set) {
558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  case 0: return &tst->arch.vex;
559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  case 1: return &tst->arch.vex_shadow1;
560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  case 2: return &tst->arch.vex_shadow2;
561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  default: vg_assert(0);
562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic int non_shadow_num_regs = 0;
566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic struct reg *non_shadow_reg_defs = NULL;
567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid initialize_shadow_low(Bool shadow_mode)
568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  if (non_shadow_reg_defs == NULL) {
570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    non_shadow_reg_defs = the_low_target.reg_defs;
571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    non_shadow_num_regs = the_low_target.num_regs;
572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  regcache_invalidate();
575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  if (the_low_target.reg_defs != non_shadow_reg_defs) {
576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     free (the_low_target.reg_defs);
577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  if (shadow_mode) {
579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    the_low_target.num_regs = 3 * non_shadow_num_regs;
580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    the_low_target.reg_defs = build_shadow_arch (non_shadow_reg_defs, non_shadow_num_regs);
581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  } else {
582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    the_low_target.num_regs = non_shadow_num_regs;
583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    the_low_target.reg_defs = non_shadow_reg_defs;
584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  set_register_cache (the_low_target.reg_defs, the_low_target.num_regs);
586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid set_desired_inferior (int use_general)
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  struct thread_info *found;
591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if (use_general == 1) {
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     found = (struct thread_info *) find_inferior_id (&all_threads,
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                      general_thread);
595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  } else {
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     found = NULL;
597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     /* If we are continuing any (all) thread(s), use step_thread
599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        to decide which thread to step and/or send the specified
600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        signal to.  */
601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     if ((step_thread != 0 && step_thread != -1)
602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         && (cont_thread == 0 || cont_thread == -1))
603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	found = (struct thread_info *) find_inferior_id (&all_threads,
604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov							 step_thread);
605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     if (found == NULL)
607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	found = (struct thread_info *) find_inferior_id (&all_threads,
608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov							 cont_thread);
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  }
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  if (found == NULL)
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     current_inferior = (struct thread_info *) all_threads.head;
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  else
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     current_inferior = found;
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  {
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     ThreadState *tst = (ThreadState *) inferior_target_data (current_inferior);
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     ThreadId tid = tst->tid;
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     dlog(1, "set_desired_inferior use_general %d found %p tid %d lwpid %d\n",
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          use_general, found, tid, tst->os_state.lwpid);
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  }
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* VG_(dmemcpy) ( void *d, const void *s, SizeT sz, Bool *mod )
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(memcmp) (d, s, sz)) {
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *mod = True;
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return VG_(memcpy) (d, s, sz);
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *mod = False;
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return d;
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_(transfer) (void *valgrind,
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    void *gdbserver,
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    transfer_direction dir,
637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    SizeT sz,
638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    Bool *mod)
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (dir == valgrind_to_gdbserver)
641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(dmemcpy) (gdbserver, valgrind, sz, mod);
642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if (dir == gdbserver_to_valgrind)
643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(dmemcpy) (valgrind, gdbserver, sz, mod);
644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vg_assert (0);
646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid valgrind_initialize_target(void)
649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGA_x86)
651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   x86_init_architecture(&the_low_target);
652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_amd64)
653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amd64_init_architecture(&the_low_target);
654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_arm)
655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   arm_init_architecture(&the_low_target);
656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_arm64)
657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   arm64_init_architecture(&the_low_target);
658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_ppc32)
659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppc32_init_architecture(&the_low_target);
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_ppc64)
661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppc64_init_architecture(&the_low_target);
662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_s390x)
663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   s390x_init_architecture(&the_low_target);
664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_mips32)
665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   mips32_init_architecture(&the_low_target);
666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_mips64)
667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   mips64_init_architecture(&the_low_target);
668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#else
669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   #error "architecture missing in target.c valgrind_initialize_target"
670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
672