mirror of https://github.com/Shizmob/smol
103 lines
4.0 KiB
Python
Executable File
103 lines
4.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
from os import path
|
|
import sys
|
|
import argparse
|
|
import shutil
|
|
import tempfile
|
|
import subprocess
|
|
|
|
from smol.util import error
|
|
from smol.elf import ELFMachine, ELF_DEFAULT_BITS
|
|
from smol.parse import decide_arch, find_lib, find_symbol, get_cc_paths, get_needed_syms
|
|
from smol.emit import output_table
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-m', '--target',
|
|
help='architecture to generate asm code for (default: auto)')
|
|
parser.add_argument('-l', '--library', metavar='LIB', action='append',
|
|
help='libraries to link against')
|
|
parser.add_argument('-L', '--libdir', metavar='DIR', action='append',
|
|
help='directories to search libraries in')
|
|
|
|
parser.add_argument('--smol-opt', metavar='OPT', default=['use_interp'], action='append',
|
|
help='optimization flags for smol')
|
|
parser.add_argument('--smol-loader-dir', metavar='DIR',
|
|
default=path.join(path.dirname(__file__), 'ldr'), help='path to smol loader files')
|
|
|
|
parser.add_argument('--nasm', default=os.getenv('NASM') or shutil.which('nasm'),
|
|
help='which nasm binary to use')
|
|
parser.add_argument('--ld', default=os.getenv('LD') or shutil.which('ld'),
|
|
help='which ld binary to use')
|
|
parser.add_argument('--cc', default=os.getenv('CC') or shutil.which('cc'),
|
|
help='which cc binary to use')
|
|
parser.add_argument('--scanelf', default=os.getenv('SCANELF') or shutil.which('scanelf'),
|
|
help='which scanelf binary to use')
|
|
parser.add_argument('--readelf', default=os.getenv('READELF') or shutil.which('readelf'),
|
|
help='which readelf binary to use')
|
|
|
|
parser.add_argument('input', nargs='+', help='input object file(s)')
|
|
parser.add_argument('-o', '--output', metavar='OUT', default='smol.out', help='output binary')
|
|
|
|
args, ld_args = parser.parse_known_args()
|
|
for util in ['nasm', 'cc', 'scanelf', 'readelf', 'ld']:
|
|
if not getattr(args, util):
|
|
parser.error('utility "{u}" could not be found! either install it or pass the path with --{u}'
|
|
.format(u=util))
|
|
|
|
opts = set()
|
|
for opt in args.smol_opt[:]:
|
|
if opt.startswith('-'):
|
|
opts.discard(opt[1:])
|
|
continue
|
|
opts.add(opt)
|
|
|
|
args.library = args.library or []
|
|
args.libdir = args.libdir or []
|
|
if args.target:
|
|
arch = args.target.tolower().replace('elf_', '')
|
|
if arch not in ELFMachine:
|
|
parser.error('unknown architecture: {}'.format(arch))
|
|
arch = ELFMachine(arch)
|
|
bits = ELF_DEFAULT_BITS[arch]
|
|
else:
|
|
arch, bits = decide_arch(args.input)
|
|
if not arch or not bits:
|
|
error('Invalid architecture!')
|
|
|
|
syms = get_needed_syms(args.readelf, args.input)
|
|
paths = get_cc_paths(args.cc)
|
|
|
|
libdirs = args.libdir + paths['libraries']
|
|
libs = []
|
|
libnames = args.library
|
|
for libname in libnames:
|
|
lib = find_lib(libdirs, libname)
|
|
if not lib:
|
|
error('could not find library: {}'.format(libname))
|
|
libs.append(lib)
|
|
|
|
symbols = {}
|
|
for symbol, reloc in syms:
|
|
library = find_symbol(args.scanelf, libs, libnames, symbol)
|
|
if not library:
|
|
error("could not find symbol: {}".format(symbol))
|
|
symbols.setdefault(library, [])
|
|
symbols[library].append((symbol, reloc))
|
|
|
|
as_args = ['-D' + opt.upper() for opt in opts]
|
|
with tempfile.NamedTemporaryFile('w', suffix='.s') as table, tempfile.NamedTemporaryFile('w', suffix='.o') as tableobj:
|
|
output_table(arch, symbols, table)
|
|
table.flush()
|
|
try:
|
|
subprocess.check_call([args.nasm] + as_args + ['-I', args.smol_loader_dir + '/', '-f', 'elf{}'.format(bits), table.name, '-o', tableobj.name])
|
|
subprocess.check_call([args.ld, '-T', os.path.join(args.smol_loader_dir, 'link.ld'), '--oformat=binary', '-o', args.output, tableobj.name] + ld_args + args.input)
|
|
except subprocess.CalledProcessError:
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|