in sql/moz-fx-data-shared-prod/telemetry_derived/crash_symbols_v1/query.py [0:0]
def _get_symbols(session, source_url, submission_date, row):
"""Get symbols needed from a single symbol file.
This may be rearchitected to use eliot by sending per-module jobs.
"""
debug_file = row["debug_file"]
debug_id = row["debug_id"]
module_offsets = row["module_offsets"]
symbols = []
if debug_file.endswith(".pdb"):
sym_filename = debug_file[:-4] + ".sym"
else:
sym_filename = debug_file + ".sym"
request_timestamp = datetime.utcnow()
try:
resp = session.get(
f"{source_url}/{debug_file}/{debug_id}/{sym_filename}",
allow_redirects=True,
)
if resp.status_code not in (400, 404):
resp.raise_for_status()
except (ConnectionError, HTTPError) as e:
print("ERROR: could not get symbols: " f"{debug_file} {debug_id} {e}")
return e, []
if resp.status_code == 404:
print("WARNING: symbols not found: " f"{debug_file} {debug_id}")
return None, []
if resp.status_code == 400:
print(
f"400 Invalid Request {resp.request.url}: "
f"{resp.request.body.decode('utf-8')!r}"
)
resp.raise_for_status()
sym_file = resp.content
norm_debug_id = symbolic.normalize_debug_id(debug_id)
sym_archive = symbolic.Archive.from_bytes(sym_file)
symcache = sym_archive.get_object(debug_id=norm_debug_id).make_symcache()
module_filename = _get_module_filename(sym_file, debug_file)
# https://github.com/mozilla-services/eliot/blob/be74cd6c0ef09dd85a71c8b1b22c3297b6b9f9bf/eliot/symbolicate_resource.py#L505-L553
for module_offset in module_offsets:
frame_info = {
"submission_date": submission_date,
"request_timestamp": request_timestamp.isoformat(),
"debug_file": debug_file,
"debug_id": debug_id,
"module_offset": hex(module_offset),
"module": module_filename,
}
if module_offset < 0:
continue # ignore invalid offset
sourceloc_list = symcache.lookup(module_offset)
if not sourceloc_list:
continue # no symbols for this offset
# sourceloc_list can have multiple entries: It starts with the innermost
# inline stack frame, and then advances to its caller, and then its
# caller, and so on, until it gets to the outer function.
# We process the outer function first, and then add inline stack frames
# afterwards. The outer function is the last item in sourceloc_list.
sourceloc = sourceloc_list[-1]
frame_info["function"] = sourceloc.symbol
frame_info["function_offset"] = hex(module_offset - sourceloc.sym_addr)
if sourceloc.full_path:
frame_info["file"] = sourceloc.full_path
# Only add a "line" if it's non-zero and not None, and if there's a
# file--otherwise the line doesn't mean anything
if sourceloc.line:
frame_info["line"] = sourceloc.line
if len(sourceloc_list) > 1:
# We have inline information. Add an "inlines" property with a list
# of { function, file, line } entries.
inlines = []
for inline_sourceloc in sourceloc_list[:-1]:
inline_data = {
"function": inline_sourceloc.symbol,
}
if inline_sourceloc.full_path:
inline_data["file"] = inline_sourceloc.full_path
if inline_sourceloc.line:
inline_data["line"] = inline_sourceloc.line
inlines.append(inline_data)
frame_info["inlines"] = inlines
symbols.append(frame_info)
return None, symbols