Esempio n. 1
0
    def build_from_git(cls, git_repo, make_target, bintool_path):
        """Build a bintool from a git repo

        This clones the repo in a temporary directory, builds it with 'make',
        then returns the filename of the resulting executable bintool

        Args:
            git_repo (str): URL of git repo
            make_target (str): Target to pass to 'make' to build the tool
            bintool_path (str): Relative path of the tool in the repo, after
                build is complete

        Returns:
            tuple:
                str: Filename of fetched file to copy to a suitable directory
                str: Name of temp directory to remove, or None
            or None on error
        """
        tmpdir = tempfile.mkdtemp(prefix='binmanf.')
        print(f"- clone git repo '{git_repo}' to '{tmpdir}'")
        tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir)
        print(f"- build target '{make_target}'")
        tools.run('make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}',
                  make_target)
        fname = os.path.join(tmpdir, bintool_path)
        if not os.path.exists(fname):
            print(f"- File '{fname}' was not produced")
            return None
        return fname, tmpdir
Esempio n. 2
0
 def ReadBlobContents(self):
     if self._strip:
         uniq = self.GetUniqueName()
         out_fname = tools.get_output_filename('%s.stripped' % uniq)
         tools.write_file(out_fname, tools.read_file(self._pathname))
         tools.run('strip', out_fname)
         self._pathname = out_fname
     super().ReadBlobContents()
     return True
Esempio n. 3
0
    def fetch_from_url(cls, url):
        """Fetch a bintool from a URL

        Args:
            url (str): URL to fetch from

        Returns:
            tuple:
                str: Filename of fetched file to copy to a suitable directory
                str: Name of temp directory to remove, or None
        """
        fname, tmpdir = tools.download(url)
        tools.run('chmod', 'a+x', fname)
        return fname, tmpdir
Esempio n. 4
0
    def apt_install(cls, package):
        """Install a bintool using the 'aot' tool

        This requires use of servo so may request a password

        Args:
            package (str): Name of package to install

        Returns:
            True, assuming it completes without error
        """
        args = ['sudo', 'apt', 'install', '-y', package]
        print('- %s' % ' '.join(args))
        tools.run(*args)
        return True
Esempio n. 5
0
def show_sym(fname, data, endian, evtype, sym):
    """Show information about an evspy entry

    Args:
        fname (str): Filename of ELF file
        data (bytes): Data for this symbol
        endian (str): Endianness to use ('little', 'big', 'auto')
        evtype (str): Event type, e.g. 'MISC_INIT_F'
        sym (elf.Symbol): Symbol to show
    """
    def _unpack_val(sym_data, offset):
        start = offset * func_size
        val_data = sym_data[start:start + func_size]
        fmt = '%s%s' % ('>' if endian == 'big' else '<',
                        'L' if func_size == 4 else 'Q')
        val = struct.unpack(fmt, val_data)[0]
        return val

    # Get the data, which is a struct evspy_info
    sym_data = data[sym.offset:sym.offset + sym.size]

    # Figure out the word size of the struct
    func_size = 4 if sym.size < 16 else 8

    # Read the function name for evspy_info->func
    while True:
        # Switch to big-endian if we see a failure
        func_addr = _unpack_val(sym_data, 0)
        func_name = elf.GetSymbolFromAddress(fname, func_addr)
        if not func_name and endian == 'auto':
            endian = 'big'
        else:
            break
    has_id = sym.size in [12, 24]
    if has_id:
        # Find the address of evspy_info->id in the ELF
        id_addr = _unpack_val(sym_data, 2)

        # Get the file offset for that address
        id_ofs = elf.GetFileOffset(fname, id_addr)

        # Read out a nul-terminated string
        id_data = data[id_ofs:id_ofs + 80]
        pos = id_data.find(0)
        if pos:
            id_data = id_data[:pos]
        id_str = id_data.decode('utf-8')
    else:
        id_str = None

    # Find the file/line for the function
    cmd = ['addr2line', '-e', fname, '%x' % func_addr]
    out = tools.run(*cmd).strip()

    # Drop the full path if it is the current directory
    if out.startswith(src_path):
        out = out[len(src_path) + 1:]
    print('%-20s  %-30s  %s' % (evtype, id_str or f'f:{func_name}', out))
Esempio n. 6
0
def BuildElfTestFiles(target_dir):
    """Build ELF files used for testing in binman

    This compiles and links the test files into the specified directory. It uses
    the Makefile and source files in the binman test/ directory.

    Args:
        target_dir: Directory to put the files into
    """
    if not os.path.exists(target_dir):
        os.mkdir(target_dir)
    testdir = os.path.join(binman_dir, 'test')

    # If binman is involved from the main U-Boot Makefile the -r and -R
    # flags are set in MAKEFLAGS. This prevents this Makefile from working
    # correctly. So drop any make flags here.
    if 'MAKEFLAGS' in os.environ:
        del os.environ['MAKEFLAGS']
    try:
        tools.run('make', '-C', target_dir, '-f',
                  os.path.join(testdir, 'Makefile'), 'SRC=%s/' % testdir)
    except ValueError as e:
        # The test system seems to suppress this in a strange way
        print(e)
Esempio n. 7
0
def GetSymbols(fname, patterns):
    """Get the symbols from an ELF file

    Args:
        fname: Filename of the ELF file to read
        patterns: List of regex patterns to search for, each a string

    Returns:
        None, if the file does not exist, or Dict:
          key: Name of symbol
          value: Hex value of symbol
    """
    stdout = tools.run('objdump', '-t', fname)
    lines = stdout.splitlines()
    if patterns:
        re_syms = re.compile('|'.join(patterns))
    else:
        re_syms = None
    syms = {}
    syms_started = False
    for line in lines:
        if not line or not syms_started:
            if 'SYMBOL TABLE' in line:
                syms_started = True
            line = None  # Otherwise code coverage complains about 'continue'
            continue
        if re_syms and not re_syms.search(line):
            continue

        space_pos = line.find(' ')
        value, rest = line[:space_pos], line[space_pos + 1:]
        flags = rest[:7]
        parts = rest[7:].split()
        section, size = parts[:2]
        if len(parts) > 2:
            name = parts[2] if parts[2] != '.hidden' else parts[3]
            syms[name] = Symbol(section, int(value, 16), int(size, 16),
                                flags[1] == 'w', None)

    # Sort dict by address
    return OrderedDict(sorted(syms.items(), key=lambda x: x[1].address))