Skip to content

Commit

Permalink
Fixed found while adding type hints (#602)
Browse files Browse the repository at this point in the history
* Fix supplementary_dwarfinfo.get_string_from{→ _}table

Fixes: e972a57 ("Supplementary object files (#426)")
Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Fix architecture specific dump

`get_section_by_name()` might return `None` in case architecture
specific dumping is requested:

```console
$ scripts/readelf.py --arch-specific test/testfiles_for_unittests/arm_with_form_indirect.elf
…
Traceback (most recent call last):
  File "scripts/readelf.py", line 1986, in <module>
    main()
  File "scripts/readelf.py", line 1956, in main
    readelf.display_arch_specific()
  File "scripts/readelf.py", line 800, in display_arch_specific
    self._display_arch_specific_arm()
  File "scripts/readelf.py", line 1832, in _display_arch_specific_arm
    self._display_attributes(attr_sec, describe_attr_tag_arm)
  File "scripts/readelf.py", line 1818, in _display_attributes
    for s in attr_sec.iter_subsections():
             ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'iter_subsections'
```

Fixes: 906f286 ("ARM build attributes section parsing (#160)")
Fixes: 43e7771 ("Add support for RISC-V attributes (#459)")
Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Fix _parse_cie_augmentation: Skip armcc augmentation

```console
$ scripts/readelf.py --debug-dump frames test/testfiles_for_unittests/arm_with_form_indirect.elf
…
Traceback (most recent call last):
  File "scripts/readelf.py", line 1988, in <module>
    main()
  File "scripts/readelf.py", line 1964, in main
    readelf.display_debug_dump(args.debug_dump_what)
  File "scripts/readelf.py", line 913, in display_debug_dump
    self._dump_debug_frames()
  File "scripts/readelf.py", line 1381, in _dump_debug_frames
    self._dwarfinfo.CFI_entries())
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "elftools/dwarf/dwarfinfo.py", line 378, in CFI_entries
    return cfi.get_entries()
           ^^^^^^^^^^^^^^^^^
  File "elftools/dwarf/callframe.py", line 79, in get_entries
    self.entries = self._parse_entries()
                   ^^^^^^^^^^^^^^^^^^^^^
  File "elftools/dwarf/callframe.py", line 88, in _parse_entries
    entries.append(self._parse_entry_at(offset))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "elftools/dwarf/callframe.py", line 144, in _parse_entry_at
    aug_bytes, aug_dict = self._parse_cie_augmentation(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "elftools/dwarf/callframe.py", line 284, in _parse_cie_augmentation
    assert augmentation.startswith(b'z'), (
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Unhandled augmentation string: b'armcc+'
```

See `decode_frame_entry_1()` from
[binutils:gdb/dwarf2/frame.c:1790-1793](https://github.com/bminor/binutils-gdb/blob/master/gdb/dwarf2/frame.c#L1790)

Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Fix several _DESCR_ATTR_TAG_ARM

```console
$ elf='test/testfiles_for_readelf/arm-eabi-attr-names.o.elf'
$ diff <(LC_ALL=C readelf -A "$elf") <(scripts/readelf.py -A "$elf")
10c10
<   Tag_THUMB_ISA_use: Thumb-1
---
>   Tag_Thumb_ISA_use: Thumb-1
16,17c16,17
<   Tag_ABI_PCS_RW_data: PC-relative
<   Tag_ABI_PCS_RO_data: PC-relative
---
>   Tag_ABI_PCS_RW_use: PC-relative
>   Tag_ABI_PCS_RO_use: PC-relative
33c33
<   Tag_compatibility: flag = 1, vendor = gnu
---
>   Tag_compatibility: Yes
```

ELF file was built using `arm-linux-gnueabi-gcc -c` using
<https://sourceware.org/git?p=binutils-gdb.git;a=blob;f=gas/testsuite/gas/arm/attr-names.s;h=c43fb88f67b7be158cceb13cb84caddaa7cd47b8;hb=HEAD>

Fixes: 906f286 ("ARM build attributes section parsing (#160)")
Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Fix several -x.text difference

```console
$ elf='test/testfiles_for_readelf/arm-eabi-attr-names.o.elf'
$ diff <(LC_ALL=C readelf -x.text "$elf") <(scripts/readelf.py -x.text "$elf")
1c1,3
< Section '.text' has no data to dump.
---
>
> Hex dump of section '.text':
>
```

Fixes: c50de91 ("Issue #119: readelf - don't do hex/string dumps for SHT_NOBITS sections")
Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Fix describing TAG_ALSO_COMPATIBLE_WITH

`d_entry[…]` will fail when `d_entry is None`:

```python
def describe_attr_tag_arm(…):
    d_entry = …
    if d_entry is None:
…
        return … + d_entry[val]
```

> Value of type "None" is not indexable

See
<https://github.com/ARM-software/abi-aa/blob/main/addenda32/addenda32.rst#secondary-compatibility-tag>.

Similar to
<https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=binutils/readelf.c;h=70d0c533f91838351c1963d4464bca71738cb245;hb=HEAD#l18228>
dump the architecture.

Fixes: 906f286 ("ARM build attributes section parsing (#160)")
Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Refactor describe_attr_tag_arm

Refactor code and lookup `_DESCR_ATTR_TAG_ARM` only once for all cases.
Also add a fallback in case the tag is not known.

Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

* Fix iter_relocations

Iterator use `yield` and must not return anything other than `None`.

Fixes: b0d7a76 ("Support getting RELR relocations from dynamic section (#509)")
Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

---------

Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
  • Loading branch information
pmhahn authored Mar 3, 2025
1 parent d34b527 commit 6c3623a
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 22 deletions.
4 changes: 4 additions & 0 deletions elftools/dwarf/callframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ def _parse_cie_augmentation(self, header, entry_structs):
if not augmentation:
return ('', {})

# Ignore armcc augmentations.
if augmentation.startswith(b'armcc'):
return (b'', {})

# Augmentation parsing works in minimal mode here: we need the length
# field to be able to skip unhandled augmentation fields.
assert augmentation.startswith(b'z'), (
Expand Down
2 changes: 1 addition & 1 deletion elftools/dwarf/dwarfinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ def replace_value(data, content_type, replacer):
replace_value(data, field.content_type, self.get_string_from_table)
elif field.form in ('DW_FORM_strp_sup', 'DW_FORM_GNU_strp_alt'):
if self.supplementary_dwarfinfo:
replace_value(data, field.content_type, self.supplementary_dwarfinfo.get_string_fromtable)
replace_value(data, field.content_type, self.supplementary_dwarfinfo.get_string_from_table)
else:
replace_value(data, field.content_type, lambda x: str(x))
elif field.form in ('DW_FORM_strp_sup', 'DW_FORM_strx', 'DW_FORM_strx1', 'DW_FORM_strx2', 'DW_FORM_strx3', 'DW_FORM_strx4'):
Expand Down
25 changes: 11 additions & 14 deletions elftools/elf/descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,30 +237,30 @@ def describe_note(x, machine):


def describe_attr_tag_arm(tag, val, extra):
s = _DESCR_ATTR_TAG_ARM.get(tag, '"%s"' % tag)
idx = ENUM_ATTR_TAG_ARM[tag] - 1
d_entry = _DESCR_ATTR_VAL_ARM[idx]

if d_entry is None:
if tag == 'TAG_COMPATIBILITY':
return (_DESCR_ATTR_TAG_ARM[tag]
+ 'flag = %d, vendor = %s' % (val, extra))
return s + 'flag = %d, vendor = %s' % (val, extra)

elif tag == 'TAG_ALSO_COMPATIBLE_WITH':
if val.tag == 'TAG_CPU_ARCH':
return _DESCR_ATTR_TAG_ARM[tag] + d_entry[val]
d_entry = _DESCR_ATTR_VAL_ARM[5] # TAG_CPU_ARCH
return s + d_entry.get(val.value, '??? (%d)' % val.value)

else:
return _DESCR_ATTR_TAG_ARM[tag] + '??? (%d)' % val.tag
return s + '??? (%d)' % val.tag

elif tag == 'TAG_NODEFAULTS':
return _DESCR_ATTR_TAG_ARM[tag] + 'True'
return s + 'True'

s = _DESCR_ATTR_TAG_ARM[tag]
s += '"%s"' % val if val else ''
return s

else:
return _DESCR_ATTR_TAG_ARM[tag] + d_entry[val]
return s + d_entry[val]

def describe_attr_tag_riscv(tag, val, extra):
idx = ENUM_ATTR_TAG_RISCV[tag] - 1
Expand Down Expand Up @@ -733,14 +733,14 @@ def _reverse_dict(d, low_priority=()):
TAG_CPU_ARCH='Tag_CPU_arch: ',
TAG_CPU_ARCH_PROFILE='Tag_CPU_arch_profile: ',
TAG_ARM_ISA_USE='Tag_ARM_ISA_use: ',
TAG_THUMB_ISA_USE='Tag_Thumb_ISA_use: ',
TAG_THUMB_ISA_USE='Tag_THUMB_ISA_use: ',
TAG_FP_ARCH='Tag_FP_arch: ',
TAG_WMMX_ARCH='Tag_WMMX_arch: ',
TAG_ADVANCED_SIMD_ARCH='Tag_Advanced_SIMD_arch: ',
TAG_PCS_CONFIG='Tag_PCS_config: ',
TAG_ABI_PCS_R9_USE='Tag_ABI_PCS_R9_use: ',
TAG_ABI_PCS_RW_DATA='Tag_ABI_PCS_RW_use: ',
TAG_ABI_PCS_RO_DATA='Tag_ABI_PCS_RO_use: ',
TAG_ABI_PCS_RW_DATA='Tag_ABI_PCS_RW_data: ',
TAG_ABI_PCS_RO_DATA='Tag_ABI_PCS_RO_data: ',
TAG_ABI_PCS_GOT_USE='Tag_ABI_PCS_GOT_use: ',
TAG_ABI_PCS_WCHAR_T='Tag_ABI_PCS_wchar_t: ',
TAG_ABI_FP_ROUNDING='Tag_ABI_FP_rounding: ',
Expand Down Expand Up @@ -951,10 +951,7 @@ def _reverse_dict(d, low_priority=()):
5: 'Prefer Accuracy',
6: 'Aggressive Accuracy',
},
{ #32 TAG_COMPATIBILITY
0: 'No',
1: 'Yes',
},
None, #32 TAG_COMPATIBILITY
None, #33
{ #34 TAG_CPU_UNALIGNED_ACCESS
0: 'None',
Expand Down
2 changes: 1 addition & 1 deletion elftools/elf/relocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def iter_relocations(self):

# If DT_RELRSZ is zero, offset is meaningless and could be None.
if self._size == 0:
return []
return

limit = self._offset + self._size
relr = self._offset
Expand Down
11 changes: 6 additions & 5 deletions scripts/readelf.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,15 +815,14 @@ def display_hex_dump(self, section_spec):
sys.stderr.write('readelf: Warning: Section \'%s\' was not dumped because it does not exist!\n' % (
section_spec))
return
if section['sh_type'] == 'SHT_NOBITS':
self._emitline("\nSection '%s' has no data to dump." % (
if section['sh_type'] == 'SHT_NOBITS' or not (data := section.data()):
self._emitline("Section '%s' has no data to dump." % (
section_spec))
return

self._emitline("\nHex dump of section '%s':" % section.name)
self._note_relocs_for_section(section)
addr = section['sh_addr']
data = section.data()
dataptr = 0

while dataptr < len(data):
Expand Down Expand Up @@ -1832,13 +1831,15 @@ def _display_arch_specific_arm(self):
""" Display the ARM architecture-specific info contained in the file.
"""
attr_sec = self.elffile.get_section_by_name('.ARM.attributes')
self._display_attributes(attr_sec, describe_attr_tag_arm)
if attr_sec:
self._display_attributes(attr_sec, describe_attr_tag_arm)

def _display_arch_specific_riscv(self):
""" Display the RISC-V architecture-specific info contained in the file.
"""
attr_sec = self.elffile.get_section_by_name('.riscv.attributes')
self._display_attributes(attr_sec, describe_attr_tag_riscv)
if attr_sec:
self._display_attributes(attr_sec, describe_attr_tag_riscv)

def _emit(self, s=''):
""" Emit an object to output
Expand Down
6 changes: 5 additions & 1 deletion test/run_readelf_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def run_test_on_file(filename, verbose=False, opt=None):
'--debug-dump=frames', '--debug-dump=frames-interp',
'--debug-dump=aranges', '--debug-dump=pubtypes',
'--debug-dump=pubnames', '--debug-dump=loc',
'--debug-dump=Ranges'
'--debug-dump=Ranges', '--arch-specific',
]
else:
options = [opt]
Expand Down Expand Up @@ -104,6 +104,10 @@ def run_test_on_file(filename, verbose=False, opt=None):
if "dwarf_v4cie" in filename and option == "--debug-dump=aranges":
continue

# TODO(pmhahn): for now only ARM works
if option in {"-A", "--arch-specific"} and "-eabi-" not in filename:
continue

# sevaa says: there is another shorted out test; in dwarf_lineprogramv5.elf, the two bytes at 0x2072 were
# patched from 0x07 0x10 to 00 00.
# Those represented the second instruction in the first FDE in .eh_frame. This changed the instruction
Expand Down
46 changes: 46 additions & 0 deletions test/testfiles_for_readelf/arm-eabi-attr-names.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@ https://sourceware.org/git?p=binutils-gdb.git;a=blob;f=gas/testsuite/gas/arm/attr-names.s;h=c43fb88f67b7be158cceb13cb84caddaa7cd47b8;hb=HEAD
@ Test ARM EABI attributes, built on x86-64:
@ arm-linux-gnueabi-gcc -o arm-eabi-attr-names.o -c arm-eabi-attr-names.S
.eabi_attribute Tag_CPU_raw_name, "random-cpu"
.eabi_attribute Tag_CPU_name, "cpu"
.eabi_attribute Tag_CPU_arch, 1
.eabi_attribute Tag_CPU_arch_profile, 'S'
.eabi_attribute Tag_ARM_ISA_use, 1
.eabi_attribute Tag_THUMB_ISA_use, 1
.eabi_attribute Tag_FP_arch, 1
.eabi_attribute Tag_VFP_arch, 1
.eabi_attribute Tag_WMMX_arch, 1
.eabi_attribute Tag_Advanced_SIMD_arch, 1
.eabi_attribute Tag_PCS_config, 1
.eabi_attribute Tag_ABI_PCS_R9_use, 1
.eabi_attribute Tag_ABI_PCS_RW_data, 1
.eabi_attribute Tag_ABI_PCS_RO_data, 1
.eabi_attribute Tag_ABI_PCS_GOT_use, 1
.eabi_attribute Tag_ABI_PCS_wchar_t, 2
.eabi_attribute Tag_ABI_FP_rounding, 1
.eabi_attribute Tag_ABI_FP_denormal, 1
.eabi_attribute Tag_ABI_FP_exceptions, 1
.eabi_attribute Tag_ABI_FP_user_exceptions, 1
.eabi_attribute Tag_ABI_FP_number_model, 1
.eabi_attribute Tag_ABI_align_needed, 1
.eabi_attribute Tag_ABI_align8_needed, 1
.eabi_attribute Tag_ABI_align_preserved, 1
.eabi_attribute Tag_ABI_align8_preserved, 1
.eabi_attribute Tag_ABI_enum_size, 1
.eabi_attribute Tag_ABI_HardFP_use, 1
.eabi_attribute Tag_ABI_VFP_args, 1
.eabi_attribute Tag_ABI_WMMX_args, 1
.eabi_attribute Tag_ABI_optimization_goals, 1
.eabi_attribute Tag_ABI_FP_optimization_goals, 1
.eabi_attribute Tag_compatibility, 1, "gnu"
.eabi_attribute Tag_CPU_unaligned_access, 1
.eabi_attribute Tag_FP_HP_extension, 1
.eabi_attribute Tag_VFP_HP_extension, 1
.eabi_attribute Tag_ABI_FP_16bit_format, 1
.eabi_attribute Tag_MPextension_use, 1
.eabi_attribute Tag_DIV_use, 1
.eabi_attribute Tag_nodefaults, 0
.eabi_attribute Tag_also_compatible_with, "\06\013"
.eabi_attribute Tag_conformance, "2.08"
.eabi_attribute Tag_T2EE_use, 1
.eabi_attribute Tag_Virtualization_use, 3
Binary file added test/testfiles_for_readelf/arm-eabi-attr-names.o.elf
Binary file not shown.

0 comments on commit 6c3623a

Please sign in to comment.