def _get_symbols()

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