Beispiel #1
0
def get_addr2line(traceback, binfile="", search_dirs=[], shlib_db=None):
    """
    Get the decode of one single OSC traceback via addr2line
    Note: 1. for DYN type binary, relative offset value is provided to addr2line;
          2. for EXEC type binary, absolute address value is provided to addr2line.

    :param traceback: one traceback in shlib+offset or +offset format
    :param binfile: the main binary file that prints the traceback
    :param search_dirs: a list of root directories to search
    :param shlib_db: the shlib_db obtained via ldd
    :returns a string containing the "addr2line offset" decode output
    """
    tokens = traceback.split("+")
    afile = tokens[0]
    thefile = ""
    if not afile:
        thefile = binfile
    else:
        if shlib_db and afile in shlib_db:
            thefile = shlib_db[afile]
        else:
            thefile = find_shlib(g_search_dirs, afile)
    verbose(
        "decoding traceback: " + traceback + " file: " + afile + " => " +
        str(thefile),
        LEVEL_1,
    )
    if not thefile or not os.path.exists(thefile):
        verbose(
            "Failed to decode because " + afile + " and " + str(thefile) +
            " do not exist!",
            LEVEL_1,
        )
        return traceback + "\n"
    offset = tokens[1]
    elf_type = get_elf_type(thefile)
    verbose(thefile + " elf_type: " + elf_type, LEVEL_1)
    if elf_type == "EXEC":
        # Calculate absolute address for EXEC type binary, which is then fed to addr2line
        base_addr = get_elf_load_base_addr(thefile)
        verbose(
            "The LOAD base address or the rounded down entry address is: " +
            hex(base_addr),
            LEVEL_1,
        )
        offset = hex(int(offset, 0) + base_addr)
        # print ("the absolute address is: " + offset)
    addr2line_prog = get_config_value("addr2line")
    if not addr2line_prog:
        addr2line_prog = "addr2line"
    cmd = addr2line_prog + " -f -i -e " + cmd_quote(
        thefile) + " " + offset + " || true"
    verbose("The traceback decode cmd is: " + cmd, LEVEL_1)
    output = subprocess.check_output(cmd,
                                     shell=True,
                                     universal_newlines=True,
                                     stderr=open(os.devnull, "w"))
    return output
Beispiel #2
0
def get_elf_class(afile):
    """
    Retrieve ELF Class of afile.

    :param afile: a file
    :returns the ELF Class of the file
    """
    if afile in g_elf_class_db:
        return g_elf_class_db[afile]
    cmd = "readelf -h " + cmd_quote(afile) + ' | grep "Class:" || true'
    output = get_shell_cmd_output(cmd)
    tokens = output.split(":")
    elf_class = tokens[1].strip()
    verbose(afile + " ELF Class is " + elf_class, LEVEL_2)
    g_elf_class_db[afile] = elf_class
    return elf_class
Beispiel #3
0
def get_elf_type(afile):
    """
    Retrieve ELF type of afile.

    :param afile: a file
    :returns the ELF type of the file
    """
    if afile in g_elf_type_db:
        return g_elf_type_db[afile]
    cmd = "readelf -h " + cmd_quote(afile) + ' | grep "Type:" || true'
    output = get_shell_cmd_output(cmd)
    tokens = output.split(":")
    elf_type = tokens[1].split()[0]
    # verbose(afile + " ELF Type is " + elf_type, LEVEL_2)
    g_elf_type_db[afile] = elf_type
    return elf_type
Beispiel #4
0
def get_entry_addr(afile):
    """
    Retrieve ELF Entry point address for a file

    :param afile: a file
    :returns the ELF Entry point address of the file
    """
    cmd = "readelf -h " + cmd_quote(
        afile) + ' | grep "Entry point address:" || true'
    output = get_shell_cmd_output(cmd)
    if output:
        tokens = output.split(":")
        entry_addr = tokens[1].split()[0]
        # verbose(afile + " entry point address is: " + entry_addr, LEVEL_2)
        return int(entry_addr, 0)
    return 0
Beispiel #5
0
    def parse(self):
        """
        Parse the Alignak configuration file

        Exit the script if some errors are encountered.

        :return: None
        """
        config = ConfigParser.ConfigParser()
        config.read(self.configuration_file)
        if config._sections == {}:
            print("Bad formatted configuration file: %s " %
                  self.configuration_file)
            sys.exit(2)

        try:
            for section in config.sections():
                if self.verbose:
                    print("Section: %s" % section)
                for (key, value) in config.items(section):
                    inner_property = "%s.%s" % (section, key)

                    # Set object property
                    setattr(self, inner_property, value)

                    # Set environment variable
                    os.environ[inner_property] = value

                    if self.verbose:
                        print(" %s = %s" % (inner_property, value))

                    if self.export:
                        # Allowed shell variables may only contain: [a-zA-z0-9_]
                        inner_property = re.sub('[^0-9a-zA-Z]+', '_',
                                                inner_property)
                        inner_property = inner_property.upper()
                        print("export %s=%s" %
                              (inner_property, cmd_quote(value)))
        except ConfigParser.InterpolationMissingOptionError as err:
            err = str(err)
            wrong_variable = err.split('\n')[3].split(':')[1].strip()
            print("Incorrect or missing variable '%s' in config file : %s" %
                  (wrong_variable, self.configuration_file))
            sys.exit(3)

        if self.verbose:
            print("Configuration file parsed correctly")
Beispiel #6
0
def get_all_shlib_paths_via_ldd(afile):
    """
    Get all the shared library paths via the ldd command for a file.

    :param afile: a file
    :returns a dictionary that contains all shlib => path mappings.
    """
    cmd = "ldd " + cmd_quote(afile) + " || true"
    ldd_output = get_shell_cmd_output(cmd)
    verbose("ldd command: " + cmd + " And output is: " + ldd_output, LEVEL_3)
    lines = ldd_output.splitlines()
    shlib_paths = dict()
    for line in lines:
        if "=>" not in line:
            continue
        tokens = line.split(" => ")
        shlib = tokens[0].strip()
        path = tokens[1].split()[0]
        if os.path.exists(path):
            shlib_paths[shlib] = path
    return shlib_paths
Beispiel #7
0
def get_elf_load_alignment(afile):
    """
    Get the alignment size of LOAD segment for afile

    :param afile: a file
    :returns the alignment size, the default is 2**16=64KB
    """
    default_load_alignment = 2**16
    objdump_prog = get_config_value("objdump")
    if not objdump_prog:
        objdump_prog = "objdump"
    cmd = objdump_prog + " -p " + cmd_quote(
        afile) + " | grep align | grep LOAD || true"
    output = get_shell_cmd_output(cmd)
    lines = output.splitlines()
    if not lines:
        return default_load_alignment
    line = lines[0]
    tokens = line.split(" align ")
    if len(tokens) < 2:
        return default_load_alignment
    alignment = tokens[1]
    verbose(afile + " LOAD alignment is: " + alignment, LEVEL_1)
    return eval(alignment)
Beispiel #8
0
    def parse(self):
        # pylint: disable=too-many-branches
        """
        Check if some extra configuration files are existing in an `alignak.d` sub directory
        near the found configuration file.

        Parse the Alignak configuration file(s)

        Exit the script if some errors are encountered.

        :return: True/False
        """
        # Search if some ini files existe in an alignak.d sub-directory
        sub_directory = 'alignak.d'
        dir_name = os.path.dirname(self.configuration_file)
        dir_name = os.path.join(dir_name, sub_directory)
        self.cfg_files = [self.configuration_file]
        if os.path.exists(dir_name):
            for root, _, walk_files in os.walk(dir_name, followlinks=True):
                for found_file in walk_files:
                    if not re.search(r"\.ini$", found_file):
                        continue
                    self.cfg_files.append(os.path.join(root, found_file))
        print("Loading configuration files: %s " % self.cfg_files)

        # Read and parse the found configuration files
        self.config = configparser.ConfigParser()
        try:
            self.config.read(self.cfg_files)
            if self.config._sections == {}:
                print("* bad formatted configuration file: %s " %
                      self.configuration_file)
                if self.embedded:
                    raise ValueError
                sys.exit(2)

            for section in self.config.sections():
                if self.verbose:
                    print("- section: %s" % section)
                for (key, value) in self.config.items(section):
                    inner_property = "%s.%s" % (section, key)

                    # Set object property
                    setattr(self, inner_property, value)

                    # Set environment variable
                    os.environ[inner_property] = value

                    if self.verbose:
                        print("  %s = %s" % (inner_property, value))

                    if self.export:
                        # Allowed shell variables may only contain: [a-zA-z0-9_]
                        inner_property = re.sub('[^0-9a-zA-Z]+', '_',
                                                inner_property)
                        inner_property = inner_property.upper()
                        print("export %s=%s" %
                              (inner_property, cmd_quote(value)))
        except configparser.ParsingError as exp:
            print("* parsing error in config file : %s\n%s" %
                  (self.configuration_file, exp.message))
            if self.embedded:
                return False
            sys.exit(3)
        except configparser.InterpolationMissingOptionError as exp:
            print("* incorrect or missing variable: %s" % str(exp))
            if self.embedded:
                return False
            sys.exit(3)

        if self.verbose:
            print("Configuration file parsed correctly")

        return True
    def parse(self):
        # pylint: disable=too-many-branches
        """
        Check if some extra configuration files are existing in an `alignak.d` sub directory
        near the found configuration file.

        Parse the Alignak configuration file(s)

        Exit the script if some errors are encountered.

        :return: True/False
        """
        # Search if some ini files existe in an alignak.d sub-directory
        sub_directory = 'alignak.d'
        dir_name = os.path.dirname(self.configuration_file)
        dir_name = os.path.join(dir_name, sub_directory)
        self.cfg_files = [self.configuration_file]
        if os.path.exists(dir_name):
            for root, _, walk_files in os.walk(dir_name, followlinks=True):
                for found_file in walk_files:
                    if not re.search(r"\.ini$", found_file):
                        continue
                    self.cfg_files.append(os.path.join(root, found_file))
        print("Loading configuration files: %s " % self.cfg_files)

        # Read and parse the found configuration files
        self.config = configparser.ConfigParser()
        try:
            self.config.read(self.cfg_files)
            if self.config._sections == {}:
                print("* bad formatted configuration file: %s " % self.configuration_file)
                if self.embedded:
                    raise ValueError
                sys.exit(2)

            for section in self.config.sections():
                if self.verbose:
                    print("- section: %s" % section)
                for (key, value) in self.config.items(section):
                    inner_property = "%s.%s" % (section, key)

                    # Set object property
                    setattr(self, inner_property, value)

                    # Set environment variable
                    os.environ[inner_property] = value

                    if self.verbose:
                        print("  %s = %s" % (inner_property, value))

                    if self.export:
                        # Allowed shell variables may only contain: [a-zA-z0-9_]
                        inner_property = re.sub('[^0-9a-zA-Z]+', '_', inner_property)
                        inner_property = inner_property.upper()
                        print("export %s=%s" % (inner_property, cmd_quote(value)))
        except configparser.ParsingError as exp:
            print("* parsing error in config file : %s\n%s"
                  % (self.configuration_file, exp.message))
            if self.embedded:
                return False
            sys.exit(3)
        except configparser.InterpolationMissingOptionError as exp:
            print("* incorrect or missing variable: %s" % str(exp))
            if self.embedded:
                return False
            sys.exit(3)

        if self.verbose:
            print("Configuration file parsed correctly")

        return True