Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: mojo/devtools/common/android_gdb/session.py

Issue 1253573008: Only update symbols on current thread when breaking or stepping in GDB. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: ppi comments & fix indentation Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/devtools/common/README.md ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """ 5 """
6 Manages a debugging session with GDB. 6 Manages a debugging session with GDB.
7 7
8 This module is meant to be imported from inside GDB. Once loaded, the 8 This module is meant to be imported from inside GDB. Once loaded, the
9 |DebugSession| attaches GDB to a running Mojo Shell process on an Android 9 |DebugSession| attaches GDB to a running Mojo Shell process on an Android
10 device using a remote gdbserver. 10 device using a remote gdbserver.
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 # This library file is not known locally. Download it from the device or 183 # This library file is not known locally. Download it from the device or
184 # the cloud and put it in cache so, if it got symbols, we can see them. 184 # the cloud and put it in cache so, if it got symbols, we can see them.
185 local_file = os.path.join(self._remote_file_cache, signature) 185 local_file = os.path.join(self._remote_file_cache, signature)
186 if not os.path.exists(local_file): 186 if not os.path.exists(local_file):
187 tmp_output = self._download_file(signature, remote_file) 187 tmp_output = self._download_file(signature, remote_file)
188 shutil.move(tmp_output, local_file) 188 shutil.move(tmp_output, local_file)
189 self._associate_symbols(mapping, local_file) 189 self._associate_symbols(mapping, local_file)
190 return True 190 return True
191 return False 191 return False
192 192
193 def _update_symbols(self): 193 def _map_symbols_on_current_thread(self, mapped_files):
194 """Updates the symbols for the current thread using files from mapped_files.
195 """
196 frame = gdb.newest_frame()
197 while frame and frame.is_valid():
198 if frame.name() is None:
199 m = self._find_mapping_for_address(mapped_files, frame.pc())
200 if m is not None and self._try_to_map(m):
201 # Force gdb to recompute its frames.
202 _gdb_execute("info threads")
203 frame = gdb.newest_frame()
204 assert frame.is_valid()
205 if (frame.older() is not None and
206 frame.older().is_valid() and
207 frame.older().pc() != frame.pc()):
208 frame = frame.older()
209 else:
210 frame = None
211
212 def update_symbols(self, current_thread_only):
194 """Updates the mapping between symbols as seen from GDB and local library 213 """Updates the mapping between symbols as seen from GDB and local library
195 files.""" 214 files.
215
216 If current_thread_only is True, only update symbols for the current thread.
217 """
196 logging.info("Updating symbols") 218 logging.info("Updating symbols")
197 mapped_files = _get_mapped_files() 219 mapped_files = _get_mapped_files()
198 _gdb_execute("info threads")
199 nb_threads = len(_gdb_execute("info threads").split("\n")) - 2
200 # Map all symbols from native libraries packages with the APK. 220 # Map all symbols from native libraries packages with the APK.
201 for file_mappings in mapped_files: 221 for file_mappings in mapped_files:
202 filename = file_mappings[0].filename 222 filename = file_mappings[0].filename
203 if ((filename.startswith('/data/data/') or 223 if ((filename.startswith('/data/data/') or
204 filename.startswith('/data/app')) and 224 filename.startswith('/data/app')) and
205 not filename.endswith('.apk') and 225 not filename.endswith('.apk') and
206 not filename.endswith('.dex')): 226 not filename.endswith('.dex')):
207 logging.info('Pre-mapping: %s' % file_mappings[0].filename) 227 logging.info('Pre-mapping: %s' % file_mappings[0].filename)
208 self._try_to_map(file_mappings) 228 self._try_to_map(file_mappings)
209 for i in xrange(nb_threads): 229
210 try: 230 if current_thread_only:
211 _gdb_execute("thread %d" % (i + 1)) 231 self._map_symbols_on_current_thread(mapped_files)
212 frame = gdb.newest_frame() 232 else:
213 while frame and frame.is_valid(): 233 logging.info('Updating all threads\' symbols')
214 if frame.name() is None: 234 current_thread = gdb.selected_thread()
215 m = self._find_mapping_for_address(mapped_files, frame.pc()) 235 nb_threads = len(_gdb_execute("info threads").split("\n")) - 2
216 if m is not None and self._try_to_map(m): 236 for i in xrange(nb_threads):
217 # Force gdb to recompute its frames. 237 try:
218 _gdb_execute("info threads") 238 _gdb_execute("thread %d" % (i + 1))
219 frame = gdb.newest_frame() 239 self._map_symbols_on_current_thread(mapped_files)
220 assert frame.is_valid() 240 except gdb.error:
221 if (frame.older() is not None and 241 traceback.print_exc()
222 frame.older().is_valid() and 242 current_thread.switch()
223 frame.older().pc() != frame.pc()):
224 frame = frame.older()
225 else:
226 frame = None
227 except gdb.error:
228 traceback.print_exc()
229 243
230 def _get_device_application_pid(self, application): 244 def _get_device_application_pid(self, application):
231 """Gets the PID of an application running on a device.""" 245 """Gets the PID of an application running on a device."""
232 output = subprocess.check_output([self._adb, 'shell', 'ps']) 246 output = subprocess.check_output([self._adb, 'shell', 'ps'])
233 for line in output.split('\n'): 247 for line in output.split('\n'):
234 elements = line.split() 248 elements = line.split()
235 if len(elements) > 0 and elements[-1] == application: 249 if len(elements) > 0 and elements[-1] == application:
236 return elements[1] 250 return elements[1]
237 return None 251 return None
238 252
(...skipping 20 matching lines...) Expand all
259 remote_file_reader_pid]) 273 remote_file_reader_pid])
260 self._remote_file_reader_process = subprocess.Popen( 274 self._remote_file_reader_process = subprocess.Popen(
261 [self._adb, 'shell', config.REMOTE_FILE_READER_DEVICE_PATH], 275 [self._adb, 'shell', config.REMOTE_FILE_READER_DEVICE_PATH],
262 stdout=subprocess.PIPE, preexec_fn = os.setpgrp) 276 stdout=subprocess.PIPE, preexec_fn = os.setpgrp)
263 port = int(self._remote_file_reader_process.stdout.readline()) 277 port = int(self._remote_file_reader_process.stdout.readline())
264 subprocess.check_call([self._adb, 'forward', 'tcp:10000', 'tcp:%d' % port]) 278 subprocess.check_call([self._adb, 'forward', 'tcp:10000', 'tcp:%d' % port])
265 self._rfc.connect() 279 self._rfc.connect()
266 280
267 _gdb_execute('target remote localhost:9999') 281 _gdb_execute('target remote localhost:9999')
268 282
269 self._update_symbols() 283 self.update_symbols(current_thread_only=False)
270 def on_stop(_): 284 def on_stop(_):
271 self._update_symbols() 285 self.update_symbols(current_thread_only=True)
272 gdb.events.stop.connect(on_stop) 286 gdb.events.stop.connect(on_stop)
273 gdb.events.exited.connect(self.stop) 287 gdb.events.exited.connect(self.stop)
288
289 # Register the update-symbols command.
290 UpdateSymbols(self)
291
292 class UpdateSymbols(gdb.Command):
293 """Command to update symbols loaded into GDB.
294
295 GDB usage: update-symbols [all|current]
296 """
297 _UPDATE_COMMAND = "update-symbols"
298
299 def __init__(self, session):
300 super(UpdateSymbols, self).__init__(self._UPDATE_COMMAND, gdb.COMMAND_STACK)
301 self._session = session
302
303 def invoke(self, arg, _unused_from_tty):
304 if arg == 'current':
305 self._session.update_symbols(current_thread_only=True)
306 else:
307 self._session.update_symbols(current_thread_only=False)
308
309 def complete(self, text, _unused_word):
310 if text == self._UPDATE_COMMAND:
311 return ('all', 'current')
312 elif text in self._UPDATE_COMMAND + ' all':
313 return ['all']
314 elif text in self._UPDATE_COMMAND + ' current':
315 return ['current']
316 else:
317 return []
OLDNEW
« no previous file with comments | « mojo/devtools/common/README.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698