| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (C) 2013 The Android Open Source Project | 3 # Copyright (C) 2013 The Android Open Source Project |
| 4 # | 4 # |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); | 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 # you may not use this file except in compliance with the License. | 6 # you may not use this file except in compliance with the License. |
| 7 # You may obtain a copy of the License at | 7 # You may obtain a copy of the License at |
| 8 # | 8 # |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 | 9 # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 # | 10 # |
| 11 # Unless required by applicable law or agreed to in writing, software | 11 # Unless required by applicable law or agreed to in writing, software |
| 12 # distributed under the License is distributed on an "AS IS" BASIS, | 12 # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 # See the License for the specific language governing permissions and | 14 # See the License for the specific language governing permissions and |
| 15 # limitations under the License. | 15 # limitations under the License. |
| 16 | 16 |
| 17 """Module for looking up symbolic debugging information. | 17 """Module for looking up symbolic debugging information. |
| 18 | 18 |
| 19 The information can include symbol names, offsets, and source locations. | 19 The information can include symbol names, offsets, and source locations. |
| 20 """ | 20 """ |
| 21 | 21 |
| 22 import glob | 22 import glob |
| 23 import itertools | 23 import itertools |
| 24 import logging |
| 24 import os | 25 import os |
| 25 import re | 26 import re |
| 26 import subprocess | 27 import subprocess |
| 27 import zipfile | 28 import zipfile |
| 28 | 29 |
| 29 CHROME_SRC = os.path.join(os.path.realpath(os.path.dirname(__file__)), | 30 CHROME_SRC = os.path.join(os.path.realpath(os.path.dirname(__file__)), |
| 30 os.pardir, os.pardir, os.pardir, os.pardir) | 31 os.pardir, os.pardir, os.pardir, os.pardir) |
| 31 ANDROID_BUILD_TOP = CHROME_SRC | 32 ANDROID_BUILD_TOP = CHROME_SRC |
| 32 SYMBOLS_DIR = CHROME_SRC | 33 SYMBOLS_DIR = CHROME_SRC |
| 33 CHROME_SYMBOLS_DIR = CHROME_SRC | 34 CHROME_SYMBOLS_DIR = CHROME_SRC |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 out_dir = os.path.join(CHROME_SYMBOLS_DIR, out_dir) | 202 out_dir = os.path.join(CHROME_SYMBOLS_DIR, out_dir) |
| 202 buildtype = os.environ.get('BUILDTYPE') | 203 buildtype = os.environ.get('BUILDTYPE') |
| 203 if buildtype: | 204 if buildtype: |
| 204 buildtype_list = [ buildtype ] | 205 buildtype_list = [ buildtype ] |
| 205 else: | 206 else: |
| 206 buildtype_list = [ 'Debug', 'Release' ] | 207 buildtype_list = [ 'Debug', 'Release' ] |
| 207 | 208 |
| 208 candidates = PathListJoin([out_dir], buildtype_list) + [CHROME_SYMBOLS_DIR] | 209 candidates = PathListJoin([out_dir], buildtype_list) + [CHROME_SYMBOLS_DIR] |
| 209 candidates = PathListJoin(candidates, dirs) | 210 candidates = PathListJoin(candidates, dirs) |
| 210 candidates = PathListJoin(candidates, [filepart]) | 211 candidates = PathListJoin(candidates, [filepart]) |
| 212 logging.debug('GetCandidates: prefiltered candidates = %s' % candidates) |
| 211 candidates = list( | 213 candidates = list( |
| 212 itertools.chain.from_iterable(map(candidate_fun, candidates))) | 214 itertools.chain.from_iterable(map(candidate_fun, candidates))) |
| 213 candidates = sorted(candidates, key=os.path.getmtime, reverse=True) | 215 candidates = sorted(candidates, key=os.path.getmtime, reverse=True) |
| 214 return candidates | 216 return candidates |
| 215 | 217 |
| 216 def GetCandidateApks(): | 218 def GetCandidateApks(): |
| 217 """Returns a list of APKs which could contain the library. | 219 """Returns a list of APKs which could contain the library. |
| 218 | 220 |
| 219 Args: | 221 Args: |
| 220 None | 222 None |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 def GetCandidateLibraries(library_name): | 277 def GetCandidateLibraries(library_name): |
| 276 """Returns a list of candidate library filenames. | 278 """Returns a list of candidate library filenames. |
| 277 | 279 |
| 278 Args: | 280 Args: |
| 279 library_name: basename of the library to match. | 281 library_name: basename of the library to match. |
| 280 | 282 |
| 281 Returns: | 283 Returns: |
| 282 A list of matching library filenames for library_name. | 284 A list of matching library filenames for library_name. |
| 283 """ | 285 """ |
| 284 return GetCandidates( | 286 return GetCandidates( |
| 285 ['lib', 'lib.target'], library_name, | 287 ['lib', 'lib.target', '.'], library_name, |
| 286 lambda filename: filter(os.path.exists, [filename])) | 288 lambda filename: filter(os.path.exists, [filename])) |
| 287 | 289 |
| 288 def TranslateLibPath(lib): | 290 def TranslateLibPath(lib): |
| 289 # SymbolInformation(lib, addr) receives lib as the path from symbols | 291 # SymbolInformation(lib, addr) receives lib as the path from symbols |
| 290 # root to the symbols file. This needs to be translated to point to the | 292 # root to the symbols file. This needs to be translated to point to the |
| 291 # correct .so path. If the user doesn't explicitly specify which directory to | 293 # correct .so path. If the user doesn't explicitly specify which directory to |
| 292 # use, then use the most recently updated one in one of the known directories. | 294 # use, then use the most recently updated one in one of the known directories. |
| 293 # If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it | 295 # If the .so is not found somewhere in CHROME_SYMBOLS_DIR, leave it |
| 294 # untranslated in case it is an Android symbol in SYMBOLS_DIR. | 296 # untranslated in case it is an Android symbol in SYMBOLS_DIR. |
| 295 library_name = os.path.basename(lib) | 297 library_name = os.path.basename(lib) |
| 296 | 298 |
| 297 # The filename in the stack trace maybe an APK name rather than a library | 299 # The filename in the stack trace maybe an APK name rather than a library |
| 298 # name. This happens when the library was loaded directly from inside the | 300 # name. This happens when the library was loaded directly from inside the |
| 299 # APK. If this is the case we try to figure out the library name by looking | 301 # APK. If this is the case we try to figure out the library name by looking |
| 300 # for a matching APK file and finding the name of the library in contains. | 302 # for a matching APK file and finding the name of the library in contains. |
| 301 # The name of the APK file on the device is of the form | 303 # The name of the APK file on the device is of the form |
| 302 # <package_name>-<number>.apk. The APK file on the host may have any name | 304 # <package_name>-<number>.apk. The APK file on the host may have any name |
| 303 # so we look at the APK badging to see if the package name matches. | 305 # so we look at the APK badging to see if the package name matches. |
| 304 if re.search('-[0-9]+[.]apk$', library_name): | 306 if re.search('-[0-9]+[.]apk$', library_name): |
| 305 mapping = MapDeviceApkToLibrary(library_name) | 307 mapping = MapDeviceApkToLibrary(library_name) |
| 306 if mapping: | 308 if mapping: |
| 307 library_name = mapping | 309 library_name = mapping |
| 308 | 310 |
| 311 logging.debug('TranslateLibPath: lib=%s library_name=%s' % (lib, library_name)
) |
| 312 |
| 309 candidate_libraries = GetCandidateLibraries(library_name) | 313 candidate_libraries = GetCandidateLibraries(library_name) |
| 314 logging.debug('TranslateLibPath: candidate_libraries=%s' % candidate_libraries
) |
| 310 if not candidate_libraries: | 315 if not candidate_libraries: |
| 311 return lib | 316 return lib |
| 312 | 317 |
| 313 library_path = os.path.relpath(candidate_libraries[0], SYMBOLS_DIR) | 318 library_path = os.path.relpath(candidate_libraries[0], SYMBOLS_DIR) |
| 319 logging.debug('TranslateLibPath: library_path=%s' % library_path) |
| 314 return '/' + library_path | 320 return '/' + library_path |
| 315 | 321 |
| 316 def SymbolInformation(lib, addr, get_detailed_info): | 322 def SymbolInformation(lib, addr, get_detailed_info): |
| 317 """Look up symbol information about an address. | 323 """Look up symbol information about an address. |
| 318 | 324 |
| 319 Args: | 325 Args: |
| 320 lib: library (or executable) pathname containing symbols | 326 lib: library (or executable) pathname containing symbols |
| 321 addr: string hexidecimal address | 327 addr: string hexidecimal address |
| 322 | 328 |
| 323 Returns: | 329 Returns: |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 process.stdin.write("\n") | 574 process.stdin.write("\n") |
| 569 process.stdin.close() | 575 process.stdin.close() |
| 570 demangled_symbol = process.stdout.readline().strip() | 576 demangled_symbol = process.stdout.readline().strip() |
| 571 process.stdout.close() | 577 process.stdout.close() |
| 572 return demangled_symbol | 578 return demangled_symbol |
| 573 | 579 |
| 574 def FormatSymbolWithOffset(symbol, offset): | 580 def FormatSymbolWithOffset(symbol, offset): |
| 575 if offset == 0: | 581 if offset == 0: |
| 576 return symbol | 582 return symbol |
| 577 return "%s+%d" % (symbol, offset) | 583 return "%s+%d" % (symbol, offset) |
| OLD | NEW |