smolemit.py 3.35 KB
Newer Older
PoroCYon's avatar
PoroCYon committed
1
2
3
4
5
6
7

import sys

from smolshared import *

def output_x86(libraries, outf):
    outf.write('; vim: set ft=nasm:\n') # be friendly
PoroCYon's avatar
PoroCYon committed
8
    outf.write('bits 32\n')
PoroCYon's avatar
PoroCYon committed
9
10
    shorts = { l: l.split('.', 1)[0].lower().replace('-', '_') for l in libraries }

PoroCYon's avatar
PoroCYon committed
11
    outf.write('%include "header32.asm"\n')
12
    outf.write('dynamic.needed:\n')
PoroCYon's avatar
PoroCYon committed
13
    for library in libraries:
PoroCYon's avatar
PoroCYon committed
14
        outf.write('dd 1;DT_NEEDED\n')
PoroCYon's avatar
PoroCYon committed
15
        outf.write('dd (_symbols.{} - _symbols)\n'.format(shorts[library]))
16
    outf.write('dynamic.end:\n')
PoroCYon's avatar
PoroCYon committed
17

18
19
20
21
#    if needgot:
#        outf.write('global _GLOBAL_OFFSET_TABLE_\n')
#        outf.write('_GLOBAL_OFFSET_TABLE_:\n')
#        outf.write('dd dynamic\n')
PoroCYon's avatar
PoroCYon committed
22
    outf.write('_symbols:\n')
23
    for library, symrels in libraries.items():
PoroCYon's avatar
PoroCYon committed
24
25
        outf.write('\t_symbols.{}: db "{}",0\n'.format(shorts[library], library))

26
27
28
29
30
31
        for sym, reloc in symrels:
            # meh
            if reloc != 'R_386_PC32':
                eprintf('Relocation type ' + reloc + ' of symbol ' + sym + ' unsupported!')
                sys.exit(1)

PoroCYon's avatar
PoroCYon committed
32
33
34
35
36
37
38
            hash = hash_djb2(sym)
            outf.write("""
\t\tglobal {name}
\t\t{name}: db 0xE9
\t\t  dd 0x{hash:x}
""".format(name=sym, hash=hash).lstrip('\n'))

PoroCYon's avatar
PoroCYon committed
39
        outf.write('\tdb 0\n') # TODO: not a dd?
PoroCYon's avatar
PoroCYon committed
40
    outf.write('db 0\n')
PoroCYon's avatar
PoroCYon committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    outf.write('_symbols.end:\n')

    outf.write('%include "loader32.asm"\n')

def output_amd64(libraries, outf):
    outf.write('; vim: set ft=nasm:\n')
    outf.write('bits 64\n')
    shorts = { l: l.split('.', 1)[0].lower().replace('-', '_') for l in libraries }

    outf.write('%include "header64.asm"\n')
    outf.write('dynamic.needed:\n')
    for library in libraries:
        outf.write('dq 1;DT_NEEDED\n')
        outf.write('dq (_symbols.{} - _symbols)\n'.format(shorts[library]))
    outf.write('dynamic.end:\n')

    outf.write('[section .data.smolgot]\n')
58
59
60
61
#    if needgot:
#        outf.write('global _GLOBAL_OFFSET_TABLE_\n')
#        outf.write('_GLOBAL_OFFSET_TABLE_:\n')
#        outf.write('dq dynamic\n')
PoroCYon's avatar
PoroCYon committed
62
    outf.write('_symbols:\n')
63
    for library, symrels in libraries.items():
PoroCYon's avatar
PoroCYon committed
64
65
        outf.write('\t_symbols.{}: db "{}",0\n'.format(shorts[library], library))

66
67
68
69
70
71
72
73
74
75
76
        for sym, reloc in symrels:
            if reloc != 'R_X86_64_PLT32' and reloc != 'R_X86_64_GOTPCRELX':
                eprintf('Relocation type ' + reloc + ' of symbol ' + sym + ' unsupported!')
                sys.exit(1)

            if reloc == 'R_X86_64_GOTPCRELX':
                outf.write("""
global {name}
{name}:
""".format(name=sym).lstrip('\n'))

PoroCYon's avatar
PoroCYon committed
77
78
79
80
81
82
83
84
85
            hash = hash_djb2(sym)
            outf.write('\t\t_symbols.{lib}.{name}: dq 0x{hash:x}\n'\
                       .format(lib=shorts[library],name=sym,hash=hash))

        outf.write('\tdq 0\n')
    outf.write('db 0\n')
    outf.write('_symbols.end:\n')

    outf.write('_smolplt:\n')
86
87
88
89
    for library, symrels in libraries.items():
        for sym, reloc in symrels:
            if reloc == 'R_X86_64_PLT32':
                outf.write("""
PoroCYon's avatar
PoroCYon committed
90
91
92
93
94
[section .text.smolplt.{name}]
global {name}
{name}:
    jmp [rel _symbols.{lib}.{name}]
""".format(lib=shorts[library],name=sym).lstrip('\n'))
PoroCYon's avatar
PoroCYon committed
95

PoroCYon's avatar
PoroCYon committed
96
97
    outf.write('_smolplt.end:\n')
    outf.write('%include "loader64.asm"\n')
PoroCYon's avatar
PoroCYon committed
98
99
def output(arch, libraries, outf):
    if arch == 'i386': output_x86(libraries, outf)
PoroCYon's avatar
PoroCYon committed
100
    elif arch == 'x86_64': output_amd64(libraries, outf)
PoroCYon's avatar
PoroCYon committed
101
102
103
104
    else:
        eprintf("E: cannot emit for arch '" + str(arch) + "'")
        sys.exit(1)