diff --git a/elftools/dwarf/callframe.py b/elftools/dwarf/callframe.py index 6e9d468e..2a2811c6 100644 --- a/elftools/dwarf/callframe.py +++ b/elftools/dwarf/callframe.py @@ -520,7 +520,7 @@ def _decode_CFI_table(self): # line that serves as the base (first) line in the FDE's table. cie = self.cie cie_decoded_table = cie.get_decoded() - if len(cie_decoded_table.table) > 0: + if cie_decoded_table.table: last_line_in_CIE = copy.copy(cie_decoded_table.table[-1]) cur_line = copy.copy(last_line_in_CIE) else: @@ -725,7 +725,8 @@ def __repr__(self): # This dictionary is filled by automatically scanning the constants module # for DW_CFA_* instructions, and mapping their values to names. Since all # names were imported from constants with `import *`, we look in globals() -_OPCODE_NAME_MAP = {} -for name in list(globals().keys()): - if name.startswith('DW_CFA'): - _OPCODE_NAME_MAP[globals()[name]] = name +_OPCODE_NAME_MAP = { + value: name + for name, value in globals().items() + if name.startswith('DW_CFA') +} diff --git a/elftools/dwarf/compileunit.py b/elftools/dwarf/compileunit.py index 704dec37..42abe1c8 100644 --- a/elftools/dwarf/compileunit.py +++ b/elftools/dwarf/compileunit.py @@ -86,7 +86,7 @@ def get_top_DIE(self): # Note that a top DIE always has minimal offset and is therefore # at the beginning of our lists, so no bisect is required. - if len(self._diemap) > 0: + if self._diemap: return self._dielist[0] top = DIE( @@ -105,7 +105,7 @@ def has_top_DIE(self): """ Returns whether the top DIE in this CU has already been parsed and cached. No parsing on demand! """ - return len(self._diemap) > 0 + return bool(self._diemap) @property def size(self): @@ -205,8 +205,7 @@ def _iter_DIE_subtree(self, die): yield die if die.has_children: for c in die.iter_children(): - for d in die.cu._iter_DIE_subtree(c): - yield d + yield from die.cu._iter_DIE_subtree(c) yield die._terminator def _get_cached_DIE(self, offset): diff --git a/elftools/dwarf/datatype_cpp.py b/elftools/dwarf/datatype_cpp.py index 55e1ae0c..68634aae 100644 --- a/elftools/dwarf/datatype_cpp.py +++ b/elftools/dwarf/datatype_cpp.py @@ -71,7 +71,7 @@ def parse_cpp_datatype(var_die): else: retval_type = "void " - if len(mods) and mods[-1] == 'pointer': + if mods and mods[-1] == 'pointer': mods.pop() t.modifiers = tuple(mods) t.name = "%s(%s*)(%s)" % (retval_type, ptr_prefix, params) @@ -147,7 +147,7 @@ def __str__(self): parts = [] # Initial const/volatile applies to the var ifself, other consts apply to the pointee - if len(mods) and mods[0] in ('const', 'volatile'): + if mods and mods[0] in ('const', 'volatile'): parts.append(mods[0]) mods = mods[1:] @@ -160,7 +160,7 @@ def __str__(self): name = '::'.join(self.scopes)+'::' + name parts.append(name) - if len(mods): + if mods: parts.append("".join(cpp_symbols[mod] for mod in mods)) if self.dimensions: @@ -190,7 +190,7 @@ def get_class_spec_if_member(func_spec, the_func): this_param = the_func.get_DIE_from_attribute('DW_AT_object_pointer') this_type = parse_cpp_datatype(this_param) class_spec = ClassDesc() - class_spec.scopes = this_type.scopes + (this_type.name,) + class_spec.scopes = (*this_type.scopes, this_type.name) class_spec.const_member = any(("const", "pointer") == this_type.modifiers[i:i+2] for i in range(len(this_type.modifiers))) # const -> pointer -> const for this arg of const return class_spec diff --git a/elftools/dwarf/descriptions.py b/elftools/dwarf/descriptions.py index 0a7c71ed..7aaf0c79 100644 --- a/elftools/dwarf/descriptions.py +++ b/elftools/dwarf/descriptions.py @@ -603,10 +603,10 @@ def dump_expr(self, expr, cu_offset=None): Returns a string representing the expression. """ parsed = self.expr_parser.parse_expr(expr) - s = [] - for deo in parsed: - s.append(self._dump_to_string(deo.op, deo.op_name, deo.args, cu_offset)) - return '; '.join(s) + return '; '.join( + self._dump_to_string(deo.op, deo.op_name, deo.args, cu_offset) + for deo in parsed + ) def _init_lookups(self): self._ops_with_decimal_arg = set([ @@ -632,7 +632,7 @@ def _dump_to_string(self, opcode, opcode_name, args, cu_offset=None): if cu_offset is None: cu_offset = 0 - if len(args) == 0: + if not args: if opcode_name.startswith('DW_OP_reg'): regnum = int(opcode_name[9:]) return '%s (%s)' % ( diff --git a/elftools/dwarf/dwarf_expr.py b/elftools/dwarf/dwarf_expr.py index 777e7481..a97bc0dd 100644 --- a/elftools/dwarf/dwarf_expr.py +++ b/elftools/dwarf/dwarf_expr.py @@ -143,7 +143,7 @@ def parse_expr(self, expr): # stream, we're done. offset = stream.tell() byte = stream.read(1) - if len(byte) == 0: + if not byte: break # Decode the opcode and its name. diff --git a/elftools/dwarf/dwarf_util.py b/elftools/dwarf/dwarf_util.py index 69615726..a24a4270 100644 --- a/elftools/dwarf/dwarf_util.py +++ b/elftools/dwarf/dwarf_util.py @@ -67,7 +67,7 @@ def _file_crc32(file): """ d = file.read(4096) checksum = 0 - while len(d): + while d: checksum = binascii.crc32(d, checksum) d = file.read(4096) return checksum diff --git a/elftools/dwarf/lineprogram.py b/elftools/dwarf/lineprogram.py index ea680f6d..88148423 100644 --- a/elftools/dwarf/lineprogram.py +++ b/elftools/dwarf/lineprogram.py @@ -61,13 +61,17 @@ def __init__(self, default_is_stmt): self.discriminator = 0 def __repr__(self): - a = ['\n' + return '\n'.join(( + '', + )) class LineProgram(object): diff --git a/elftools/dwarf/structs.py b/elftools/dwarf/structs.py index 0f05c1b1..153dcdc2 100644 --- a/elftools/dwarf/structs.py +++ b/elftools/dwarf/structs.py @@ -375,7 +375,7 @@ def _create_lineprog_header(self): # past it. Therefore an If is used. self.Dwarf_lineprog_file_entry = Struct('file_entry', CString('name'), - If(lambda ctx: len(ctx.name) != 0, + If(lambda ctx: bool(ctx.name), Embed(Struct('', self.Dwarf_uleb128('dir_index'), self.Dwarf_uleb128('mtime'), @@ -452,7 +452,7 @@ def _parse(self, stream, context): CString('include_directory'))), If(lambda ctx: ctx.version < 5, RepeatUntilExcluding( - lambda obj, ctx: len(obj.name) == 0, + lambda obj, ctx: not obj.name, self.Dwarf_lineprog_file_entry)) # array name is file_entry ) diff --git a/elftools/dwarf/typeunit.py b/elftools/dwarf/typeunit.py index 4df82377..8e38a944 100644 --- a/elftools/dwarf/typeunit.py +++ b/elftools/dwarf/typeunit.py @@ -102,7 +102,7 @@ def get_top_DIE(self): # Note that a top DIE always has minimal offset and is therefore # at the beginning of our lists, so no bisect is required. - if len(self._diemap) > 0: + if self._diemap: return self._dielist[0] top = DIE( @@ -121,7 +121,7 @@ def has_top_DIE(self): """ Returns whether the top DIE in this TU has already been parsed and cached. No parsing on demand! """ - return len(self._diemap) > 0 + return bool(self._diemap) @property def size(self): @@ -219,8 +219,7 @@ def _iter_DIE_subtree(self, die): yield die if die.has_children: for c in die.iter_children(): - for d in die.cu._iter_DIE_subtree(c): - yield d + yield from die.cu._iter_DIE_subtree(c) yield die._terminator def _get_cached_DIE(self, offset): diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index c492cd1b..2d7a20ce 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -398,13 +398,14 @@ def get_ehabi_infos(self): Object file contains many .ARM.exidx sections. So we must traverse every section and filter sections whose type is SHT_ARM_EXIDX. """ - _ret = [] if self['e_type'] == 'ET_REL': # TODO: support relocatable file assert False, "Current version of pyelftools doesn't support relocatable file." - for section in self.iter_sections(type='SHT_ARM_EXIDX'): - _ret.append(EHABIInfo(section, self.little_endian)) - return _ret if len(_ret) > 0 else None + _ret = [ + EHABIInfo(section, self.little_endian) + for section in self.iter_sections(type='SHT_ARM_EXIDX') + ] + return _ret if _ret else None def get_machine_arch(self): """ Return the machine architecture, as detected from the ELF header. diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index 3805962e..60c38625 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -346,7 +346,7 @@ def num_attributes(self): def attributes(self): """ List of all attributes in the subsubsection. """ - return [self.header] + list(self.iter_attributes()) + return [self.header, *(self.iter_attributes())] def _make_attributes(self): """ Create all attributes for this subsubsection except the first one diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index 3a7ca668..62cdf3b4 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -273,7 +273,7 @@ def _create_rel(self): self.Elf_addr('r_offset'), *fields) - fields_and_addend = fields + [self.Elf_sxword('r_addend')] + fields_and_addend = [*fields, self.Elf_sxword('r_addend')] self.Elf_Rela = Struct('Elf_Rela', self.Elf_addr('r_offset'), *fields_and_addend diff --git a/scripts/dwarfdump.py b/scripts/dwarfdump.py index 234eeaca..2c15757d 100644 --- a/scripts/dwarfdump.py +++ b/scripts/dwarfdump.py @@ -220,10 +220,10 @@ def _desc_operationarg(s, cu): elif isinstance(s, int): return hex(s) elif isinstance(s, list): # Could be a blob (list of ints), could be a subexpression - if len(s) > 0 and isinstance(s[0], DWARFExprOp): # Subexpression + if s and isinstance(s[0], DWARFExprOp): # Subexpression return '(' + '; '.join(_desc_operation(op.op, op.op_name, op.args, cu) for op in s) + ')' else: - return " ".join((hex(len(s)),) + tuple("0x%02x" % b for b in s)) + return " ".join((hex(len(s)), *("0x%02x" % b for b in s))) def _arch(cu): return cu.dwarfinfo.config.machine_arch diff --git a/scripts/readelf.py b/scripts/readelf.py index 71f85575..afa83f5b 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -1263,7 +1263,7 @@ def _dump_debug_line_programs(self): ver5 = lineprogram.header.version >= 5 cu_filename = bytes2str(lineprogram['file_entry'][0].name) - if len(lineprogram['include_directory']) > 0: + if lineprogram['include_directory']: # GNU readelf 2.38 only outputs directory in wide mode self._emitline('%s:' % cu_filename) else: @@ -1394,7 +1394,7 @@ def _dump_debug_namelut(self, what): section = self._dwarfinfo.debug_pubtypes_sec # readelf prints nothing if the section is not present. - if namelut is None or len(namelut) == 0: + if not namelut: return self._emitline('Contents of the %s section:' % section.name) @@ -1428,7 +1428,7 @@ def _dump_debug_aranges(self): # dumps them, so we should too. unordered_entries = aranges_table._get_entries(need_empty=True) - if len(unordered_entries) == 0: + if not unordered_entries: self._emitline() self._emitline("Section '.debug_aranges' has no debugging data.") return @@ -1505,7 +1505,7 @@ def _dump_frames_interp_info(self, section, cfi_entries): # Decode the table. decoded_table = entry.get_decoded() - if len(decoded_table.table) == 0: + if not decoded_table.table: continue # Print the heading row for the decoded table @@ -1521,7 +1521,7 @@ def _dump_frames_interp_info(self, section, cfi_entries): # DWARF register number is not greater than other GPRs.) decoded_table = entry.get_decoded() reg_order = sorted(decoded_table.reg_order) - if len(decoded_table.reg_order): + if decoded_table.reg_order: # Headings for the registers for regnum in reg_order: if regnum == ra_regnum: @@ -1602,7 +1602,7 @@ def _dump_debug_locsection(self, di, loc_lists_sec): line_template = " %%08x %%0%dx %%0%dx %%s%%s" % (addr_width, addr_width) loc_lists = list(loc_lists_sec.iter_location_lists()) - if len(loc_lists) == 0: + if not loc_lists: # Present but empty locations section - readelf outputs a message self._emitline("\nSection '%s' has no debugging data." % (section_name,)) return @@ -1703,7 +1703,7 @@ def _dump_debug_loclists_CU_header(self, cu): self._emitline(' Address size: %d' % cu.address_size) self._emitline(' Segment size: %d' % cu.segment_selector_size) self._emitline(' Offset entries: %d\n' % cu.offset_count) - if cu.offsets and len(cu.offsets): + if cu.offsets: self._emitline(' Offsets starting at 0x%x:' % cu.offset_table_offset) for i_offset in enumerate(cu.offsets): self._emitline(' [%6d] 0x%x' % i_offset) @@ -1728,7 +1728,7 @@ def _dump_debug_rnglists_CU_header(self, cu): self._emitline(' Address size: %d' % cu.address_size) self._emitline(' Segment size: %d' % cu.segment_selector_size) self._emitline(' Offset entries: %d\n' % cu.offset_count) - if cu.offsets and len(cu.offsets): + if cu.offsets: self._emitline(' Offsets starting at 0x%x:' % cu.offset_table_offset) for i_offset in enumerate(cu.offsets): self._emitline(' [%6d] 0x%x' % i_offset) @@ -1755,7 +1755,7 @@ def _dump_debug_rangesection(self, di, range_lists_sec): next_rcu_offset = 0 range_lists = list(range_lists_sec.iter_range_lists()) - if len(range_lists) == 0: + if not range_lists: # Present but empty ranges section - readelf outputs a message self._emitline("\nSection '%s' has no debugging data." % section_name) return diff --git a/test/all_tests.py b/test/all_tests.py index 5ee3821d..deff7b9b 100755 --- a/test/all_tests.py +++ b/test/all_tests.py @@ -11,7 +11,7 @@ from utils import is_in_rootdir def run_test_script(path, *args): - cmd = [sys.executable, path] + list(args) + cmd = [sys.executable, path, *args] print("Running '%s'" % ' '.join(cmd)) subprocess.check_call(cmd) diff --git a/test/run_dwarfdump_tests.py b/test/run_dwarfdump_tests.py index 629db01f..aaf475ee 100644 --- a/test/run_dwarfdump_tests.py +++ b/test/run_dwarfdump_tests.py @@ -109,7 +109,7 @@ def compare_output(s1, s2): s1 = s1.replace('(0x0000000000000000 ".text")', '(0x0000000000000000)') def prepare_lines(s): - return [line for line in s.lower().splitlines() if line.strip() != ''] + return [line for line in s.lower().splitlines() if line.strip()] lines1 = prepare_lines(s1) lines2 = prepare_lines(s2) @@ -169,7 +169,7 @@ def main(): # If file names are given as command-line arguments, only these files # are taken as inputs. Otherwise, autodiscovery is performed. - if len(args.files) > 0: + if args.files: filenames = args.files else: filenames = sorted(discover_testfiles('test/testfiles_for_dwarfdump')) diff --git a/test/run_readelf_tests.py b/test/run_readelf_tests.py index 18c33853..203ba493 100755 --- a/test/run_readelf_tests.py +++ b/test/run_readelf_tests.py @@ -163,7 +163,7 @@ def compare_output(s1, s2): to replicate. Read the documentation for more details. """ def prepare_lines(s): - return [line for line in s.lower().splitlines() if line.strip() != ''] + return [line for line in s.lower().splitlines() if line.strip()] lines1 = prepare_lines(s1) lines2 = prepare_lines(s2) @@ -299,7 +299,7 @@ def main(): # If file names are given as command-line arguments, only these files # are taken as inputs. Otherwise, autodiscovery is performed. - if len(args.files) > 0: + if args.files: filenames = args.files else: filenames = sorted(discover_testfiles('test/testfiles_for_readelf')) diff --git a/test/test_dynamic.py b/test/test_dynamic.py index a310d8ae..71706bd6 100644 --- a/test/test_dynamic.py +++ b/test/test_dynamic.py @@ -39,17 +39,16 @@ class TestDynamic(unittest.TestCase): def test_missing_sections(self): """Verify we can get dynamic strings w/out section headers""" - libs = [] with open(os.path.join('test', 'testfiles_for_unittests', 'aarch64_super_stripped.elf'), 'rb') as f: elf = ELFFile(f) - for segment in elf.iter_segments(): - if segment.header.p_type != 'PT_DYNAMIC': - continue - - for t in segment.iter_tags(): - if t.entry.d_tag == 'DT_NEEDED': - libs.append(t.needed) + libs = [ + t.needed + for segment in elf.iter_segments() + if segment.header.p_type == 'PT_DYNAMIC' + for t in segment.iter_tags() + if t.entry.d_tag == 'DT_NEEDED' + ] exp = ['libc.so.6'] self.assertEqual(libs, exp) diff --git a/test/utils.py b/test/utils.py index dcdc483a..3fc76ad0 100644 --- a/test/utils.py +++ b/test/utils.py @@ -14,7 +14,7 @@ def run_exe(exe_path, args=[], echo=False): list of arguments. Captures its return code (rc) and stdout and returns a pair: rc, stdout_str """ - popen_cmd = [exe_path] + args + popen_cmd = [exe_path, *args] if os.path.splitext(exe_path)[1] == '.py': popen_cmd.insert(0, sys.executable) if echo: