建立 MAG160C 逆向工程交接仓库
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# elftools: dwarf/dwarf_utils.py
|
||||
#
|
||||
# Minor, shared DWARF helpers
|
||||
#
|
||||
# Eli Bendersky (eliben@gmail.com)
|
||||
# This code is in the public domain
|
||||
#-------------------------------------------------------------------------------
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import binascii
|
||||
from typing import IO, TYPE_CHECKING, Any
|
||||
|
||||
from ..construct.macros import Array
|
||||
from ..common.exceptions import DWARFError
|
||||
from ..common.utils import preserve_stream_pos, struct_parse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
|
||||
from ..construct import Struct
|
||||
from .compileunit import CompileUnit
|
||||
from .structs import DWARFStructs
|
||||
from .typeunit import TypeUnit
|
||||
|
||||
|
||||
def _get_base_offset(cu: CompileUnit | TypeUnit, base_attribute_name: str) -> int:
|
||||
"""Retrieves a required, base offset-type atribute
|
||||
from the top DIE in the CU. Applies to several indirectly
|
||||
encoded objects - range lists, location lists, strings, addresses.
|
||||
"""
|
||||
cu_top_die = cu.get_top_DIE()
|
||||
if base_attribute_name not in cu_top_die.attributes:
|
||||
raise DWARFError("The CU at offset 0x%x needs %s" % (cu.cu_offset, base_attribute_name))
|
||||
return cu_top_die.attributes[base_attribute_name].value
|
||||
|
||||
def _resolve_via_offset_table(
|
||||
stream: IO[bytes],
|
||||
cu: CompileUnit | TypeUnit,
|
||||
index: int,
|
||||
base_attribute_name: str,
|
||||
) -> int:
|
||||
"""Given an index in the offset table and directions where to find it,
|
||||
retrieves an offset. Works for loclists, rnglists.
|
||||
|
||||
The DWARF offset bitness of the CU block in the section matches that
|
||||
of the CU record in dwarf_info. See DWARFv5 standard, section 7.4.
|
||||
|
||||
This is used for translating DW_FORM_loclistx, DW_FORM_rnglistx
|
||||
via the offset table in the respective section.
|
||||
"""
|
||||
base_offset = _get_base_offset(cu, base_attribute_name)
|
||||
# That's offset (within the rnglists/loclists/str_offsets section) of
|
||||
# the offset table for this CU's block in that section, which in turn is indexed by the index.
|
||||
|
||||
offset_size = 4 if cu.structs.dwarf_format == 32 else 8
|
||||
with preserve_stream_pos(stream):
|
||||
return base_offset + struct_parse(cu.structs.the_Dwarf_offset, stream, base_offset + index*offset_size)
|
||||
|
||||
def _iter_CUs_in_section(
|
||||
stream: IO[bytes],
|
||||
structs: DWARFStructs,
|
||||
parser: Struct,
|
||||
) -> Iterator[Any]:
|
||||
"""Iterates through the list of CU sections in loclists or rangelists. Almost identical structures there.
|
||||
|
||||
get_parser is a lambda that takes structs, returns the parser
|
||||
"""
|
||||
stream.seek(0, os.SEEK_END)
|
||||
endpos = stream.tell()
|
||||
stream.seek(0, os.SEEK_SET)
|
||||
|
||||
offset = 0
|
||||
while offset < endpos:
|
||||
header = struct_parse(parser, stream, offset)
|
||||
if header.offset_count > 0:
|
||||
offset_parser = structs.Dwarf_uint64 if header.is64 else structs.Dwarf_uint32
|
||||
header['offsets'] = struct_parse(Array(header.offset_count, offset_parser('')), stream)
|
||||
else:
|
||||
header['offsets'] = False
|
||||
yield header
|
||||
offset = header.offset_after_length + header.unit_length
|
||||
|
||||
def _file_crc32(file: IO[bytes]) -> int:
|
||||
""" Provided a readable binary stream, reads the stream to the end
|
||||
and computes the CRC32 checksum of its contents,
|
||||
with the initial value of 0.
|
||||
"""
|
||||
d = file.read(4096)
|
||||
checksum = 0
|
||||
while d:
|
||||
checksum = binascii.crc32(d, checksum)
|
||||
d = file.read(4096)
|
||||
return checksum
|
||||
Reference in New Issue
Block a user