ronantakizawa/codereview-bench huggingface dataset:
Repository: mandiant/capa
File: tests/test_main.py (Python)

Code before:
    for addr, info in std_json["meta"]["analysis"]["layout"]["functions"]:
        if addr == ["absolute", 0x10001010]:
            assert {"address": ["absolute", 0x10001179]} in info["matched_basic_blocks"]


def test_main_dotnet(_1c444_dotnetfile_extractor):
    # tests successful execution and all output modes
    path = _1c444_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0
    assert capa.main.main([path, "-v"]) == 0
    assert capa.main.main([path, "-j"]) == 0
    assert capa.main.main([path, "-q"]) == 0
    assert capa.main.main([path]) == 0


def test_main_dotnet2(_692f_dotnetfile_extractor):
    # tests successful execution and one rendering
    # above covers all output modes
    path = _692f_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0


def test_main_dotnet3(_0953c_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _0953c_dotnetfile_extractor.path
    assert capa.main.main([path, "-j"]) == 0


def test_main_dotnet4(_039a6_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _039a6_dotnetfile_extractor.path
    assert capa.main.main([path]) == 0


Review comment (suggestion):
```suggestion
    assert capa.main.main([path, "-vv"]) == 0
```

Code after:
    for addr, info in std_json["meta"]["analysis"]["layout"]["functions"]:
        if addr == ["absolute", 0x10001010]:
            assert {"address": ["absolute", 0x10001179]} in info["matched_basic_blocks"]


def test_main_dotnet(_1c444_dotnetfile_extractor):
    # tests successful execution and all output modes
    path = _1c444_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0
    assert capa.main.main([path, "-v"]) == 0
    assert capa.main.main([path, "-j"]) == 0
    assert capa.main.main([path, "-q"]) == 0
    assert capa.main.main([path]) == 0


def test_main_dotnet2(_692f_dotnetfile_extractor):
    # tests successful execution and one rendering
    # above covers all output modes
    path = _692f_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0


def test_main_dotnet3(_0953c_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _0953c_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0


def test_main_dotnet4(_039a6_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _039a6_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0
Repository: mandiant/capa
File: tests/test_main.py (Python)

Code before:
    # tests successful execution and all output modes
    path = _1c444_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0
    assert capa.main.main([path, "-v"]) == 0
    assert capa.main.main([path, "-j"]) == 0
    assert capa.main.main([path, "-q"]) == 0
    assert capa.main.main([path]) == 0


def test_main_dotnet2(_692f_dotnetfile_extractor):
    # tests successful execution and one rendering
    # above covers all output modes
    path = _692f_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0


def test_main_dotnet3(_0953c_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _0953c_dotnetfile_extractor.path
    assert capa.main.main([path, "-j"]) == 0


def test_main_dotnet4(_039a6_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _039a6_dotnetfile_extractor.path
    assert capa.main.main([path]) == 0


Review comment (suggestion):
```suggestion
    assert capa.main.main([path, "-vv"]) == 0
```

Code after:
    # tests successful execution and all output modes
    path = _1c444_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0
    assert capa.main.main([path, "-v"]) == 0
    assert capa.main.main([path, "-j"]) == 0
    assert capa.main.main([path, "-q"]) == 0
    assert capa.main.main([path]) == 0


def test_main_dotnet2(_692f_dotnetfile_extractor):
    # tests successful execution and one rendering
    # above covers all output modes
    path = _692f_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0


def test_main_dotnet3(_0953c_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _0953c_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0


def test_main_dotnet4(_039a6_dotnetfile_extractor):
    # tests successful execution and one rendering
    path = _039a6_dotnetfile_extractor.path
    assert capa.main.main([path, "-vv"]) == 0
Repository: mandiant/capa
File: capa/features/common.py (Python)

Code before:


OS_WINDOWS = "windows"
OS_LINUX = "linux"
OS_MACOS = "macos"
# dotnet
OS_ANY = "any"
VALID_OS = {os.value for os in capa.features.extractors.elf.OS}
VALID_OS.update({OS_WINDOWS, OS_LINUX, OS_MACOS, OS_ANY})


class OS(Feature):
    def __init__(self, value: str, description=None):
        super().__init__(value, description=description)
        self.name = "os"


FORMAT_PE = "pe"
FORMAT_ELF = "elf"
FORMAT_DOTNET = "dotnet"
VALID_FORMAT = (FORMAT_PE, FORMAT_ELF, FORMAT_DOTNET)
# internal only, not to be used in rules
FORMAT_AUTO = "auto"
FORMAT_SC32 = "sc32"
FORMAT_SC64 = "sc64"
FORMAT_FREEZE = "freeze"
FORMAT_UNKNOWN = "unknown"


class Format(Feature):
    def __init__(self, value: str, description=None):
        super().__init__(value, description=description)
        self.name = "format"


def is_global_feature(feature):
    """
    is this a feature that is extracted at every scope?
    today, these are OS and arch features.
    """
    return isinstance(feature, (OS, Arch))


Review comment (refactor):
interesting, so we support both a rule specifying `OS_ANY` and also an extractor emitting the feature `OS_ANY`. cool!

Code after:


OS_WINDOWS = "windows"
OS_LINUX = "linux"
OS_MACOS = "macos"
# dotnet
OS_ANY = "any"
VALID_OS = {os.value for os in capa.features.extractors.elf.OS}
VALID_OS.update({OS_WINDOWS, OS_LINUX, OS_MACOS, OS_ANY})


class OS(Feature):
    def __init__(self, value: str, description=None):
        super().__init__(value, description=description)
        self.name = "os"

    def evaluate(self, ctx, **kwargs):
        capa.perf.counters["evaluate.feature"] += 1
        capa.perf.counters["evaluate.feature." + self.name] += 1

        for feature, locations in ctx.items():
            if not isinstance(feature, (OS,)):
                continue

            assert isinstance(feature.value, str)
            if OS_ANY in (self.value, feature.value) or self.value == feature.value:
                return Result(True, self, [], locations=locations)

        return Result(False, self, [])


FORMAT_PE = "pe"
FORMAT_ELF = "elf"
FORMAT_DOTNET = "dotnet"
VALID_FORMAT = (FORMAT_PE, FORMAT_ELF, FORMAT_DOTNET)
# internal only, not to be used in rules
FORMAT_AUTO = "auto"
FORMAT_SC32 = "sc32"
FORMAT_SC64 = "sc64"
FORMAT_FREEZE = "freeze"
FORMAT_UNKNOWN = "unknown"


class Format(Feature):
    def __init__(self, value: str, description=None):
        super().__init__(value, description=description)
        self.name = "format"


def is_global_feature(feature):
    """
Repository: mandiant/capa
File: scripts/import-to-ida.py (Python)

Code before:
    a = doc["meta"]["sample"]["md5"].lower()
    b = ida_nalt.retrieve_input_file_md5().lower()
    if not a.startswith(b):
        logger.error("sample mismatch")
        return -2

    rows = []
    for rule in doc["rules"].values():
        if rule["meta"].get("lib"):
            continue
        if rule["meta"].get("capa/subscope"):
            continue
        if rule["meta"]["scope"] != "function":
            continue

        name = rule["meta"]["name"]
        ns = rule["meta"].get("namespace", "")
        for va in rule["matches"].keys():
            va = int(va)
            rows.append((ns, name, va))

    # order by (namespace, name) so that like things show up together
    rows = sorted(rows)
    for ns, name, va in rows:
        if ns:
            cmt = f"{name} ({ns})"
        else:
            cmt = f"{name}"

        logger.info("0x%x: %s", va, cmt)
        try:
            # message will look something like:
            #
            #     capa: delete service (host-interaction/service/delete)
            append_func_cmt(va, "capa: " + cmt, repeatable=False)
        except ValueError:
            continue

    logger.info("ok")


main()


Review comment (suggestion):
```suggestion
            cmt = name + " ({ns})"
```

Code after:
    a = doc["meta"]["sample"]["md5"].lower()
    b = ida_nalt.retrieve_input_file_md5().lower()
    if not a.startswith(b):
        logger.error("sample mismatch")
        return -2

    rows = []
    for rule in doc["rules"].values():
        if rule["meta"].get("lib"):
            continue
        if rule["meta"].get("capa/subscope"):
            continue
        if rule["meta"]["scope"] != "function":
            continue

        name = rule["meta"]["name"]
        ns = rule["meta"].get("namespace", "")
        for va in rule["matches"].keys():
            va = int(va)
            rows.append((ns, name, va))

    # order by (namespace, name) so that like things show up together
    rows = sorted(rows)
    for ns, name, va in rows:
        if ns:
            cmt = name + f"({ns})"
        else:
            cmt = name

        logger.info("0x%x: %s", va, cmt)
        try:
            # message will look something like:
            #
            #     capa: delete service (host-interaction/service/delete)
            append_func_cmt(va, "capa: " + cmt, repeatable=False)
        except ValueError:
            continue

    logger.info("ok")


main()
Repository: mandiant/capa
File: capa/features/extractors/elf.py (Python)

Code before:


def guess_os_from_needed_dependencies(elf) -> Optional[OS]:
    for needed in elf.needed:
        if needed.startswith("libmachuser.so"):
            return OS.HURD
        if needed.startswith("libhurduser.so"):
            return OS.HURD

    return None


def guess_os_from_symtab(elf) -> Optional[OS]:
    SHT_SYMTAB = 0x2
    SHT_STRTAB = 0x3

    for shdr in elf.section_headers:
        if shdr.type == SHT_STRTAB:
            strtab_buf, strtab_sz= shdr.buf, shdr.size

        elif shdr.type == SHT_SYMTAB:
            symtab_buf, symtab_entsize, symtab_sz = shdr.buf, shdr.entsize, shdr.size

    if None in (strtab_buf, symtab_buf):
        # executable does not contain a symbol table
		# or the symbol's names are stripped
        return None
    
    symtab = SYMTAB(
        elf.endian, elf.bitness, symtab_buf, symtab_entsize, symtab_sz, strtab_buf, strtab_sz
        )

    keywords = {
        OS.LINUX: ['linux', '/linux/',],
        }
    
    for name, *_ in symtab.get_symbols():
        sym_name = symtab.fetch_str(name)

        for os, hints in keywords.items():
            if any(map(lambda x: x in sym_name, hints)):
                return os
    
    return None


def detect_elf_os(f) -> str:
    """
    f: type Union[BinaryIO, IDAIO]
    """
    elf = ELF(f)

Review comment (suggestion):
```suggestion
        # executable does not contain a symbol table
        # or the symbol's names are stripped
```

mixed tabs and spaces here

Code after:
                # we don't have any good guesses based on versions needed
                pass

    return None


def guess_os_from_needed_dependencies(elf) -> Optional[OS]:
    for needed in elf.needed:
        if needed.startswith("libmachuser.so"):
            return OS.HURD
        if needed.startswith("libhurduser.so"):
            return OS.HURD

    return None


def guess_os_from_symtab(elf) -> Optional[OS]:
    SHT_SYMTAB = 0x2
    SHT_STRTAB = 0x3
    strtab_buf = symtab_buf = None

    for shdr in elf.section_headers:
        if shdr.type == SHT_STRTAB:
            strtab_buf, strtab_sz= shdr.buf, shdr.size

        elif shdr.type == SHT_SYMTAB:
            symtab_buf, symtab_entsize, symtab_sz = shdr.buf, shdr.entsize, shdr.size

    if None in (strtab_buf, symtab_buf):
        # executable does not contain a symbol table
        # or the symbol's names are stripped
        return None
    
    symtab = SymTab(
        elf.endian, elf.bitness, symtab_buf, symtab_entsize, symtab_sz, strtab_buf, strtab_sz
    )

    keywords = {
        OS.LINUX: ['linux', '/linux/',],
    }
    
    for name, *_ in symtab.get_symbols():
        sym_name = symtab.fetch_str(name)

        for os, hints in keywords.items():
            if any(map(lambda x: x in sym_name, hints)):
                return os
    
    return None
Repository: mandiant/capa
File: capa/features/extractors/elf.py (Python)

Code before:
    return None


def guess_os_from_symtab(elf) -> Optional[OS]:
    SHT_SYMTAB = 0x2
    SHT_STRTAB = 0x3

    for shdr in elf.section_headers:
        if shdr.type == SHT_STRTAB:
            strtab_buf, strtab_sz= shdr.buf, shdr.size

        elif shdr.type == SHT_SYMTAB:
            symtab_buf, symtab_entsize, symtab_sz = shdr.buf, shdr.entsize, shdr.size

    if None in (strtab_buf, symtab_buf):
        # executable does not contain a symbol table
		# or the symbol's names are stripped
        return None
    
    symtab = SYMTAB(
        elf.endian, elf.bitness, symtab_buf, symtab_entsize, symtab_sz, strtab_buf, strtab_sz
        )

    keywords = {
        OS.LINUX: ['linux', '/linux/',],
        }
    
    for name, *_ in symtab.get_symbols():
        sym_name = symtab.fetch_str(name)

        for os, hints in keywords.items():
            if any(map(lambda x: x in sym_name, hints)):
                return os
    
    return None


def detect_elf_os(f) -> str:
    """
    f: type Union[BinaryIO, IDAIO]
    """
    elf = ELF(f)

    osabi_guess = guess_os_from_osabi(elf)
    logger.debug("guess: osabi: %s", osabi_guess)

    ph_notes_guess = guess_os_from_ph_notes(elf)
    logger.debug("guess: ph notes: %s", ph_notes_guess)

    sh_notes_guess = guess_os_from_sh_notes(elf)
    logger.debug("guess: sh notes: %s", sh_notes_guess)

Review comment (suggestion):
```suggestion
    symtab = SYMTAB(
        elf.endian, elf.bitness, symtab_buf, symtab_entsize, symtab_sz, strtab_buf, strtab_sz
    )

    keywords = {
        OS.LINUX: ['linux', '/linux/',],
    }
```

Code after:
            return OS.HURD
        if needed.startswith("libhurduser.so"):
            return OS.HURD

    return None


def guess_os_from_symtab(elf) -> Optional[OS]:
    SHT_SYMTAB = 0x2
    SHT_STRTAB = 0x3
    strtab_buf = symtab_buf = None

    for shdr in elf.section_headers:
        if shdr.type == SHT_STRTAB:
            strtab_buf, strtab_sz= shdr.buf, shdr.size

        elif shdr.type == SHT_SYMTAB:
            symtab_buf, symtab_entsize, symtab_sz = shdr.buf, shdr.entsize, shdr.size

    if None in (strtab_buf, symtab_buf):
        # executable does not contain a symbol table
        # or the symbol's names are stripped
        return None
    
    symtab = SymTab(
        elf.endian, elf.bitness, symtab_buf, symtab_entsize, symtab_sz, strtab_buf, strtab_sz
    )

    keywords = {
        OS.LINUX: ['linux', '/linux/',],
    }
    
    for name, *_ in symtab.get_symbols():
        sym_name = symtab.fetch_str(name)

        for os, hints in keywords.items():
            if any(map(lambda x: x in sym_name, hints)):
                return os
    
    return None


def detect_elf_os(f) -> str:
    """
    f: type Union[BinaryIO, IDAIO]
    """
    elf = ELF(f)

    osabi_guess = guess_os_from_osabi(elf)
    logger.debug("guess: osabi: %s", osabi_guess)
Repository: mandiant/capa
File: capa/features/extractors/elf.py (Python)

Code before:
class Shdr:
    name: int
    type: int
    flags: int
    addr: int
    offset: int
    size: int
    link: int
    entsize: int
    buf: bytes

    @classmethod
    def from_viv(cls, section, buf: bytes):
        """
        construct a Shdr object from vivisect's representation of
        section headers (Elf.Elf32Section or Elf.Elf64Section)
        """
        return cls(
            int(section.vsGetField("sh_name")),
            int(section.vsGetField("sh_type")),
            int(section.vsGetField("sh_flags")),
            int(section.vsGetField("sh_addr")),
            int(section.vsGetField("sh_offset")),
            int(section.vsGetField("sh_size")),
            int(section.vsGetField("sh_link")),
            int(section.vsGetField("sh_entsize")),
            buf,
        )


class ELF:
    def __init__(self, f: BinaryIO):
        self.f = f

        # these will all be initialized in `_parse()`
        self.bitness: int
        self.endian: str
        self.e_phentsize: int
        self.e_phnum: int
        self.e_shentsize: int
        self.e_shnum: int
        self.phbuf: bytes
        self.shbuf: bytes

        self._parse()

    def _parse(self):
        self.f.seek(0x0)
        self.file_header = self.f.read(0x40)

        if not self.file_header.startswith(b"\x7fELF"):

Review comment (suggestion):
```suggestion
            section.sh_name,
            section.sh_type,
            section.sh_flags,
            section.sh_addr,
            section.sh_offset,
            section.sh_size,
            section.sh_link,
            section.sh_entsize,
```

I think you can access the properties of a vstruct directly.

Code after:
class Shdr:
    name: int
    type: int
    flags: int
    addr: int
    offset: int
    size: int
    link: int
    entsize: int
    buf: bytes

    @classmethod
    def from_viv(cls, section, buf: bytes) -> "Shdr":
        return cls(
            section.sh_name,
            section.sh_type,
            section.sh_flags,
            section.sh_addr,
            section.sh_offset,
            section.sh_size,
            section.sh_link,
            section.sh_entsize,
            buf,
        )


class ELF:
    def __init__(self, f: BinaryIO):
        self.f = f

        # these will all be initialized in `_parse()`
        self.bitness: int
        self.endian: str
        self.e_phentsize: int
        self.e_phnum: int
        self.e_shentsize: int
        self.e_shnum: int
        self.phbuf: bytes
        self.shbuf: bytes

        self._parse()

    def _parse(self):
        self.f.seek(0x0)
        self.file_header = self.f.read(0x40)

        if not self.file_header.startswith(b"\x7fELF"):
            raise CorruptElfFile("missing magic header")

        ei_class, ei_data = struct.unpack_from("BB", self.file_header, 4)
        logger.debug("ei_class: 0x%02x ei_data: 0x%02x", ei_class, ei_data)
Repository: mandiant/capa
File: tests/test_scripts.py (Python)

Code before:
                    meta:
                        name: Test Rule 4
                        scope: function
                    features:
                      - not:
                        - string: "expa"
            """
        ),
    }

    """
        The rule_overlaps list represents the number of overlaps between each rule in the RULESET.
        An overlap includes a rule overlap with itself.
        The overlaps are like:
        - Rule 0 has zero overlaps in RULESET
        - Rule 1 overlaps with 3 other rules in RULESET
        - Rule 4 overlaps with itself in RULESET
        These overlap values indicate the number of rules with which
        each rule in RULESET has overlapping features.
    """
    rule_overlaps = [0, 3, 4, 4, 1]

    rule_dir = tmpdir.mkdir("capa_rule_overlap_test")
    rule_paths = []

    rule_file = tmpdir.join("%s.yml" % "rule_0")
    rule_file.write(TEST_RULE_0)
    rule_paths.append(rule_file.strpath)

    for rule_name, RULE_CONTENT in TEST_RULESET.items():
        rule_file = rule_dir.join("%s.yml" % rule_name)
        rule_file.write(RULE_CONTENT)
        rule_paths.append(rule_file.strpath)

    # tests if number of overlaps for rules in RULESET found are correct.
    for expected_overlaps, rule_path in zip(rule_overlaps, rule_paths):
        overlaps_found = run_detect_duplicate_features(rule_dir.strpath, rule_path)
        assert overlaps_found.returncode == expected_overlaps


Review comment (suggestion):
```suggestion
    rule_file = tmpdir.join("rule_0.yml")
```

Code after:
        The overlaps are like:
        - Rule 0 has zero overlaps in RULESET
        - Rule 1 overlaps with 3 other rules in RULESET
        - Rule 4 overlaps with itself in RULESET
        These overlap values indicate the number of rules with which
        each rule in RULESET has overlapping features.
    """
    rule_overlaps = [0, 4, 3, 3, 1]

    rule_dir = tmpdir.mkdir("capa_rule_overlap_test")
    rule_paths = []

    rule_file = tmpdir.join("rule_0.yml")
    rule_file.write(TEST_RULE_0)
    rule_paths.append(rule_file.strpath)

    for rule_name, RULE_CONTENT in TEST_RULESET.items():
        rule_file = rule_dir.join("%s.yml" % rule_name)
        rule_file.write(RULE_CONTENT)
        rule_paths.append(rule_file.strpath)

    # tests if number of overlaps for rules in RULESET found are correct.
    script_path = get_script_path("detect_duplicate_features.py")
    for expected_overlaps, rule_path in zip(rule_overlaps, rule_paths):
        args = [rule_dir.strpath, rule_path]
        overlaps_found = run_program(script_path, args)
        assert overlaps_found.returncode == expected_overlaps
Repository: mandiant/capa
File: capa/features/extractors/elf.py (Python)

Code before:

    keywords = {
        OS.LINUX: [
            "linux",
            "/linux/",
        ],
    }

    for symbol in symtab.get_symbols():
        sym_name = symtab.get_name(symbol)

        for os, hints in keywords.items():
            if any(map(lambda x: x in sym_name, hints)):
                return os

    return None


def detect_elf_os(f) -> str:
    """
    f: type Union[BinaryIO, IDAIO]
    """
    try:
        elf = ELF(f)
    except Exception as e:
        logger.debug(f"Error parsing ELF file: {str(e)}")
        return "unknown"

    try:
        osabi_guess = guess_os_from_osabi(elf)
        logger.debug("guess: osabi: %s", osabi_guess)
    except Exception as e:
        logger.debug(f"Error guessing OS from OSABI: {str(e)}")
        osabi_guess = None

    try:
        ph_notes_guess = guess_os_from_ph_notes(elf)
        logger.debug("guess: ph notes: %s", ph_notes_guess)
    except Exception as e:
        logger.debug(f"Error guessing OS from program header notes: {str(e)}")
        ph_notes_guess = None

    try:
        sh_notes_guess = guess_os_from_sh_notes(elf)
        logger.debug("guess: sh notes: %s", sh_notes_guess)
    except Exception as e:
        logger.debug(f"Error guessing OS from section header notes: {str(e)}")
        sh_notes_guess = None

    try:
        linker_guess = guess_os_from_linker(elf)

Review comment (bug):
please avoid pre-formatting strings that are passed to a logger, because the logger has some optimizations.
```suggestion
        logger.debug(f"Error parsing ELF file: %s", e)
```

Code after:

    keywords = {
        OS.LINUX: [
            "linux",
            "/linux/",
        ],
    }

    for symbol in symtab.get_symbols():
        sym_name = symtab.get_name(symbol)

        for os, hints in keywords.items():
            if any(map(lambda x: x in sym_name, hints)):
                return os

    return None


def detect_elf_os(f) -> str:
    """
    f: type Union[BinaryIO, IDAIO]
    """
    try:
        elf = ELF(f)
    except Exception as e:
        logger.warning("Error parsing ELF file: %s", e)
        return "unknown"

    try:
        osabi_guess = guess_os_from_osabi(elf)
        logger.debug("guess: osabi: %s", osabi_guess)
    except Exception as e:
        logger.warning("Error guessing OS from OSABI: %s", e)
        osabi_guess = None

    try:
        ph_notes_guess = guess_os_from_ph_notes(elf)
        logger.debug("guess: ph notes: %s", ph_notes_guess)
    except Exception as e:
        logger.warning("Error guessing OS from program header notes: %s", e)
        ph_notes_guess = None

    try:
        sh_notes_guess = guess_os_from_sh_notes(elf)
        logger.debug("guess: sh notes: %s", sh_notes_guess)
    except Exception as e:
        logger.warning("Error guessing OS from section header notes: %s", e)
        sh_notes_guess = None

    try:
        linker_guess = guess_os_from_linker(elf)