eliben / pyelftools

Parsing ELF and DWARF in Python
Other
2.02k stars 511 forks source link

Cortex M33 elf binary error: no decoding mapping for 46 [tag] #484

Closed KShingala closed 1 year ago

KShingala commented 1 year ago

I am trying to use angr to generate control flow graph for CM33 binary but get this error from elftool from backend_z3.py.

I am using the following in my script to

arch = archinfo.ArchARM(archinfo.Endness.LE) p = angr.Project('my_binary.elf', arch=arch)

Can someone help me what I am doing wrong?

sevaa commented 1 year ago

Tag 0x46 is DW_TAG_dynamic_type. It's documented in DWARFv5, but for some reason not listed in the tag enum of pyelftools. It's a fairly simple fix on our side, but who knows when will the current state of the master branch get released. PR #487 will address that.

eliben commented 1 year ago

@KShingala if #487 did not fix your issue, please provide a simple, minimal self-contained reproducer which includes the Python code using pyelftools and the sample binary.

KShingala commented 1 year ago

Here are the file I used to experience the error. example.zip

sevaa commented 1 year ago

Reproduced. This is not about a DWARF tag 0x46, like I thought, the error is taking place while parsing the .ARM.attributes section, and the enum that is lacking 46 (decimal) is ENUM_ATTR_TAG_ARM under elf/enums.py.

Now I need to find an authoritative reference on those, figure out what does 46 stand for, and how does one parse the rest of the attribute record... EDIT: this seems to be it: https://github.com/ARM-software/abi-aa/blob/main/addenda32/addenda32.rst#introduction-to-build-attributes

In case someone else is interested in debugging, here is a repro example that is not encumbered with a ton of dependencies (mind the data file path though):

from elftools.elf.elffile import ELFFile
from elftools.elf.sections import ARMAttributesSubsection, ARMAttributesSubsubsection

with open('temp\\example.elf', 'rb') as file:
    reader = ELFFile(file)

    attrs_sec = reader.get_section_by_name(".ARM.attributes")
    attrs_sub_sec = next(s for s in attrs_sec.subsections if isinstance(s, ARMAttributesSubsection))
    attrs_sub_sub_sec = next(s for s in attrs_sub_sec.subsubsections if isinstance(s, ARMAttributesSubsubsection))
    atts = {}
    for attobj in attrs_sub_sub_sec.attributes:
        atts[attobj.tag] = attobj.value

Even if my first hunch was wrong, filling a gap in the DWARF tag enum was a Good Thing. :)

@KShingala: may we add the attached binary to the repository and use it in the autotest?

KShingala commented 1 year ago

I dont mind using the binary as an autotest, please feel free to use it as you like.

sevaa commented 1 year ago

Either way, the fix seems to be a new enum value - but in a different enum. See the changeset in #491, and see if you can apply that.