Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PoroCYon
smol
Commits
c75be623
Commit
c75be623
authored
Mar 28, 2019
by
PoroCYon
Committed by
PoroCYon
Apr 29, 2019
Browse files
32-bit version using dnload loader now working
parent
d9dbaae2
Changes
9
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
c75be623
...
@@ -13,7 +13,7 @@ BITS ?= $(shell getconf LONG_BIT)
...
@@ -13,7 +13,7 @@ BITS ?= $(shell getconf LONG_BIT)
COPTFLAGS
=
-Os
-fno-plt
-fno-stack-protector
-fno-stack-check
-fno-unwind-tables
\
COPTFLAGS
=
-Os
-fno-plt
-fno-stack-protector
-fno-stack-check
-fno-unwind-tables
\
-fno-asynchronous-unwind-tables
-fomit-frame-pointer
-ffast-math
-no-pie
\
-fno-asynchronous-unwind-tables
-fomit-frame-pointer
-ffast-math
-no-pie
\
-fno-pic
-fno-PIE
-m64
-march
=
core2
-ffunction-sections
-fdata-sections
-fno-pic
-fno-PIE
-m64
-march
=
core2
-ffunction-sections
-fdata-sections
-fno-plt
CXXOPTFLAGS
=
$(COPTFLAGS)
-fno-exceptions
\
CXXOPTFLAGS
=
$(COPTFLAGS)
-fno-exceptions
\
-fno-rtti
-fno-enforce-eh-specs
-fnothrow-opt
-fno-use-cxa-get-exception-ptr
\
-fno-rtti
-fno-enforce-eh-specs
-fnothrow-opt
-fno-use-cxa-get-exception-ptr
\
-fno-implicit-templates
-fno-threadsafe-statics
-fno-use-cxa-atexit
-fno-implicit-templates
-fno-threadsafe-statics
-fno-use-cxa-atexit
...
@@ -41,7 +41,7 @@ CXXFLAGS += -m$(BITS) $(shell pkg-config --cflags sdl2)
...
@@ -41,7 +41,7 @@ CXXFLAGS += -m$(BITS) $(shell pkg-config --cflags sdl2)
LIBS
=
-lc
LIBS
=
-lc
SMOLFLAGS
+=
SMOLFLAGS
+=
ASFLAGS
+=
-DUSE_INTERP
-DALIGN_STACK
ASFLAGS
+=
-DUSE_INTERP
-DUSE_DNLOAD_LOADER
-DNO_START_ARG
-DUNSAFE_DYNAMIC
#
-DALIGN_STACK
#-DUSE_DNLOAD_LOADER #-DUSE_DT_DEBUG #-DUSE_DL_FINI #-DNO_START_ARG #-DUNSAFE_DYNAMIC
#-DUSE_DNLOAD_LOADER #-DUSE_DT_DEBUG #-DUSE_DL_FINI #-DNO_START_ARG #-DUNSAFE_DYNAMIC
NASM
?=
nasm
NASM
?=
nasm
...
...
README.md
View file @
c75be623
...
@@ -19,7 +19,8 @@ ld -T ld/link.ld --oformat=binary -o output.elf nasm-output.o input.o...
...
@@ -19,7 +19,8 @@ ld -T ld/link.ld --oformat=binary -o output.elf nasm-output.o input.o...
*
`ALIGN_STACK`
:
*64-bit only*
: realign the stack so that SSE instructions
*
`ALIGN_STACK`
:
*64-bit only*
: realign the stack so that SSE instructions
won't segfault. Costs 1 byte.
won't segfault. Costs 1 byte.
*
`USE_NX`
: Don't use
`RWE`
segments at all. Not very well tested. Costs the
*
`USE_NX`
: Don't use
`RWE`
segments at all. Not very well tested. Costs the
size of 1 phdr.
size of 1 phdr, plus some extra stuff on
`i386`
. Don't forget to pass
`-n`
to
`smol.py`
as well.
*
`USE_DL_FINI`
: keep track of the
`_dl_fini`
function and pass it to your
*
`USE_DL_FINI`
: keep track of the
`_dl_fini`
function and pass it to your
`_start`
. Costs 2 bytes, plus maybe a few more depending on how it's passed
`_start`
. Costs 2 bytes, plus maybe a few more depending on how it's passed
to
`__libc_start_main`
.
to
`__libc_start_main`
.
...
@@ -29,9 +30,10 @@ ld -T ld/link.ld --oformat=binary -o output.elf nasm-output.o input.o...
...
@@ -29,9 +30,10 @@ ld -T ld/link.ld --oformat=binary -o output.elf nasm-output.o input.o...
strictly worse size-wise by 10 (i386) or 3 (x86_64) bytes.
strictly worse size-wise by 10 (i386) or 3 (x86_64) bytes.
*
`SKIP_ENTRIES`
: skip the first two entries of the
`struct link_map`
, which
*
`SKIP_ENTRIES`
: skip the first two entries of the
`struct link_map`
, which
represent the main binary and the vDSO. Costs around 5 bytes.
represent the main binary and the vDSO. Costs around 5 bytes.
*
`USE_DNLOAD_LOADER`
:
*64-bit only*
: use the symbol loading mechanism as used
*
`USE_DNLOAD_LOADER`
: use the symbol loading mechanism as used in dnload (i.e.
in dnload (i.e. traverse the symtab of the imported libraries). Slightly
traverse the symtab of the imported libraries). Slightly larger, but probably
larger, but probably better compressable.
better compressable and more compatible with other libcs and future versions
of glibc.
*
`NO_START_ARG`
:
*don't*
pass the stack pointer to
`_start`
as the first arg.
*
`NO_START_ARG`
:
*don't*
pass the stack pointer to
`_start`
as the first arg.
Will make it unable to read argc/argv/environ, but gives you 3 bytes.
Will make it unable to read argc/argv/environ, but gives you 3 bytes.
...
@@ -55,6 +57,10 @@ optional arguments:
...
@@ -55,6 +57,10 @@ optional arguments:
--cc CC which cc binary to use
--cc CC which cc binary to use
--scanelf SCANELF which scanelf binary to use
--scanelf SCANELF which scanelf binary to use
--readelf READELF which readelf binary to use
--readelf READELF which readelf binary to use
-n, --nx Use NX (i.e. don't use RWE pages). Costs the size of
one phdr, plus some extra bytes on i386. Don't forget
to pass -DUSE_NX to the assembly loader as well!
```
```
A minimal crt (and
`_start`
funcion) are provided in case you want to use
`main`
.
A minimal crt (and
`_start`
funcion) are provided in case you want to use
`main`
.
...
...
smol.py
View file @
c75be623
...
@@ -34,6 +34,9 @@ def main():
...
@@ -34,6 +34,9 @@ def main():
# help="Use dnload's mechanism of importing functions. Slightly larger, but usually better compressable.")
# help="Use dnload's mechanism of importing functions. Slightly larger, but usually better compressable.")
# parser.add_argument('--libsep', default=False, action='store_true', \
# parser.add_argument('--libsep', default=False, action='store_true', \
# help="Separete import symbols per library, instead of looking at every library when resolving a symbol.")
# help="Separete import symbols per library, instead of looking at every library when resolving a symbol.")
parser
.
add_argument
(
'-n'
,
'--nx'
,
default
=
False
,
action
=
'store_true'
,
\
help
=
"Use NX (i.e. don't use RWE pages). Costs the size of one phdr, "
\
+
"plus some extra bytes on i386."
)
parser
.
add_argument
(
'input'
,
nargs
=
'+'
,
help
=
"input object file"
)
parser
.
add_argument
(
'input'
,
nargs
=
'+'
,
help
=
"input object file"
)
parser
.
add_argument
(
'output'
,
type
=
argparse
.
FileType
(
'w'
),
\
parser
.
add_argument
(
'output'
,
type
=
argparse
.
FileType
(
'w'
),
\
...
@@ -66,7 +69,7 @@ def main():
...
@@ -66,7 +69,7 @@ def main():
symbols
.
setdefault
(
library
,
[])
symbols
.
setdefault
(
library
,
[])
symbols
[
library
].
append
((
symbol
,
reloc
))
symbols
[
library
].
append
((
symbol
,
reloc
))
output
(
arch
,
symbols
,
args
.
output
)
output
(
arch
,
symbols
,
args
.
nx
,
args
.
output
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
()
main
()
...
...
smolemit.py
View file @
c75be623
...
@@ -3,8 +3,26 @@ import sys
...
@@ -3,8 +3,26 @@ import sys
from
smolshared
import
*
from
smolshared
import
*
def
output_x86
(
libraries
,
outf
):
def
output_x86
(
libraries
,
nx
,
outf
):
outf
.
write
(
'; vim: set ft=nasm:
\n
'
)
# be friendly
outf
.
write
(
'; vim: set ft=nasm:
\n
'
)
# be friendly
if
nx
:
outf
.
write
(
'%define USE_NX 1
\n
'
)
usedrelocs
=
set
({})
for
library
,
symrels
in
libraries
.
items
():
for
sym
,
reloc
in
symrels
:
usedrelocs
.
add
(
reloc
)
if
not
(
nx
)
and
'R_386_PC32'
in
usedrelocs
and
'R_386_GOT32X'
in
usedrelocs
:
eprintf
(
"Using a mix of R_386_PC32 and R_386_GOT32X relocations! "
+
\
"Please change a few C compiler flags and recompile your code."
)
exit
(
1
)
use_jmp_bytes
=
not
nx
and
'R_386_PC32'
in
usedrelocs
if
use_jmp_bytes
:
outf
.
write
(
'%define USE_JMP_BYTES 1
\n
'
)
outf
.
write
(
'bits 32
\n
'
)
outf
.
write
(
'bits 32
\n
'
)
shorts
=
{
l
:
l
.
split
(
'.'
,
1
)[
0
].
lower
().
replace
(
'-'
,
'_'
)
for
l
in
libraries
}
shorts
=
{
l
:
l
.
split
(
'.'
,
1
)[
0
].
lower
().
replace
(
'-'
,
'_'
)
for
l
in
libraries
}
...
@@ -14,39 +32,57 @@ def output_x86(libraries, outf):
...
@@ -14,39 +32,57 @@ def output_x86(libraries, outf):
for
library
in
libraries
:
for
library
in
libraries
:
outf
.
write
(
'dd 1;DT_NEEDED
\n
'
)
outf
.
write
(
'dd 1;DT_NEEDED
\n
'
)
outf
.
write
(
'dd (_symbols.{} - _strtab)
\n
'
.
format
(
shorts
[
library
]))
outf
.
write
(
'dd (_symbols.{} - _strtab)
\n
'
.
format
(
shorts
[
library
]))
outf
.
write
(
'dynamic.end:
\n
'
)
outf
.
write
(
"""
\
dynamic.end:
%ifndef UNSAFE_DYNAMIC
dd DT_NULL
%endif
"""
)
# if needgot:
outf
.
write
(
'[section .rodata.neededlibs]
\n
'
)
# outf.write('global _GLOBAL_OFFSET_TABLE_\n')
# outf.write('_GLOBAL_OFFSET_TABLE_:\n')
# outf.write('dd dynamic\n')
outf
.
write
(
'_strtab:
\n
'
)
outf
.
write
(
'_strtab:
\n
'
)
# if not libsep:
# for library, symrels in libraries.items():
# outf.write('\t_symbols.{}: db "{}",0\n'.format(shorts[library], library))
outf
.
write
(
'_symbols:
\n
'
)
for
library
,
symrels
in
libraries
.
items
():
for
library
,
symrels
in
libraries
.
items
():
# if libsep:
outf
.
write
(
'
\t
_symbols.{}: db "{}",0
\n
'
.
format
(
shorts
[
library
],
library
))
outf
.
write
(
'
\t
_symbols.{}: db "{}",0
\n
'
.
format
(
shorts
[
library
],
library
))
outf
.
write
(
'[section .data.smolgot]
\n
'
)
if
not
nx
:
outf
.
write
(
'[section .text.smolplt]
\n
'
)
outf
.
write
(
'_symbols:
\n
'
)
for
library
,
symrels
in
libraries
.
items
():
for
sym
,
reloc
in
symrels
:
for
sym
,
reloc
in
symrels
:
# meh
# meh
if
reloc
!=
'R_386_PC32'
:
if
reloc
!=
'R_386_PC32'
and
reloc
!=
'R_386_GOT32X'
:
eprintf
(
'Relocation type '
+
reloc
+
' of symbol '
+
sym
+
' unsupported!'
)
eprintf
(
'Relocation type '
+
reloc
+
' of symbol '
+
sym
+
' unsupported!'
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
hash
=
hash_djb2
(
sym
)
hash
=
hash_djb2
(
sym
)
outf
.
write
(
"""
if
nx
:
outf
.
write
(
"
\t\t
_symbols.{lib}.{name}: dd 0x{hash:x}"
\
.
format
(
lib
=
shorts
[
library
],
name
=
sym
,
hash
=
hash
).
lstrip
(
'
\n
'
))
else
:
outf
.
write
((
"""
\
\t\t
global {name}
\t\t
global {name}
\t\t
{name}:
db 0xE9
\t\t
{name}:
"""
+
(
"
\n\t\t\t
db 0xE9"
if
use_jmp_bytes
else
''
)
+
"""
\t\t
dd 0x{hash:x}
\t\t
\t
dd 0x{hash:x}
"""
.
format
(
name
=
sym
,
hash
=
hash
).
lstrip
(
'
\n
'
))
"""
)
.
format
(
name
=
sym
,
hash
=
hash
).
lstrip
(
'
\n
'
))
outf
.
write
(
'
\t
db 0
\n
'
)
# TODO: not a dd?
outf
.
write
(
'db 0
\n
'
)
outf
.
write
(
'db 0
\n
'
)
outf
.
write
(
'_symbols.end:
\n
'
)
outf
.
write
(
'_symbols.end:
\n
'
)
if
nx
:
outf
.
write
(
'_smolplt:
\n
'
)
for
library
,
symrels
in
libraries
.
items
():
for
sym
,
reloc
in
symrels
:
outf
.
write
(
"""
\
[section .text.smolplt.{name}]
global {name}
{name}:
\t
jmp [dword _symbols.{lib}.{name}]
"""
.
format
(
lib
=
shorts
[
library
],
name
=
sym
).
lstrip
(
'
\n
'
))
outf
.
write
(
'_smolplt.end:
\n
'
)
outf
.
write
(
'%include "loader32.asm"
\n
'
)
outf
.
write
(
'%include "loader32.asm"
\n
'
)
# end output_x86
# end output_x86
...
@@ -104,11 +140,11 @@ global {name}
...
@@ -104,11 +140,11 @@ global {name}
for
library
,
symrels
in
libraries
.
items
():
for
library
,
symrels
in
libraries
.
items
():
for
sym
,
reloc
in
symrels
:
for
sym
,
reloc
in
symrels
:
if
reloc
==
'R_X86_64_PLT32'
:
if
reloc
==
'R_X86_64_PLT32'
:
outf
.
write
(
"""
outf
.
write
(
"""
\
[section .text.smolplt.{name}]
[section .text.smolplt.{name}]
global {name}
global {name}
{name}:
{name}:
jmp [rel _symbols.{lib}.{name}]
\t
jmp [rel _symbols.{lib}.{name}]
"""
.
format
(
lib
=
shorts
[
library
],
name
=
sym
).
lstrip
(
'
\n
'
))
"""
.
format
(
lib
=
shorts
[
library
],
name
=
sym
).
lstrip
(
'
\n
'
))
outf
.
write
(
'_smolplt.end:
\n
'
)
outf
.
write
(
'_smolplt.end:
\n
'
)
...
@@ -116,8 +152,8 @@ global {name}
...
@@ -116,8 +152,8 @@ global {name}
# end output_amd64
# end output_amd64
def
output
(
arch
,
libraries
,
outf
):
def
output
(
arch
,
libraries
,
nx
,
outf
):
if
arch
==
'i386'
:
output_x86
(
libraries
,
outf
)
if
arch
==
'i386'
:
output_x86
(
libraries
,
nx
,
outf
)
elif
arch
==
'x86_64'
:
output_amd64
(
libraries
,
outf
)
elif
arch
==
'x86_64'
:
output_amd64
(
libraries
,
outf
)
else
:
else
:
eprintf
(
"E: cannot emit for arch '"
+
str
(
arch
)
+
"'"
)
eprintf
(
"E: cannot emit for arch '"
+
str
(
arch
)
+
"'"
)
...
...
src/elf.inc
View file @
c75be623
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
%
define
PHDR_X
(
1
)
%
define
PHDR_X
(
1
)
%
define
DT_NULL
(
0
)
%
define
DT_NULL
(
0
)
%
define
DT_NEEDED
(
1
)
%
define
DT_STRTAB
(
5
)
%
define
DT_STRTAB
(
5
)
%
define
DT_SYMTAB
(
6
)
%
define
DT_SYMTAB
(
6
)
%
define
DT_DEBUG
(
21
)
%
define
DT_DEBUG
(
21
)
...
@@ -36,6 +37,15 @@
...
@@ -36,6 +37,15 @@
%
define
ST_NAME_OFF
(
0
)
%
define
ST_NAME_OFF
(
0
)
;
,
----
not
16
?
;
,
----
not
16
?
;
v
;
v
%
define
ST_VALUE_OFF
(
8
)
%
if
__BITS__
==
32
%
define
SYMTAB_SIZE
(
24
)
%
define
D_UN_PTR_OFF
(
4
)
%
define
ST_VALUE_OFF
(
4
)
%
define
SYMTAB_SIZE
(
16
)
%
define
ELF_DYN_SZ
(
8
)
%
else
%
define
D_UN_PTR_OFF
(
8
)
%
define
ST_VALUE_OFF
(
8
)
%
define
SYMTAB_SIZE
(
24
)
%
define
ELF_DYN_SZ
(
16
)
%
endif
src/header32.asm
View file @
c75be623
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
%include "elf.inc"
%include "elf.inc"
heade
r:
ehd
r:
; e_ident
; e_ident
db
0x7F
,
"ELF"
db
0x7F
,
"ELF"
db
EI_CLASS
,
EI_DATA
,
EI_VERSION
,
EI_OSABI
db
EI_CLASS
,
EI_DATA
,
EI_VERSION
,
EI_OSABI
...
@@ -17,11 +17,11 @@ header:
...
@@ -17,11 +17,11 @@ header:
dw
ELF_MACHINE
; e_machine: 3 = x86
dw
ELF_MACHINE
; e_machine: 3 = x86
dd
EI_VERSION
; e_version
dd
EI_VERSION
; e_version
dd
_smol_start
; e_entry
dd
_smol_start
; e_entry
dd
(
.segments
-
header
)
; e_phoff
dd
(
phdr
-
ehdr
)
; e_phoff
dd
0
; e_shoff
dd
0
; e_shoff
dd
0
; e_flags
dd
0
; e_flags
dw
(
.segments
-
header
)
; e_ehsize
dw
(
phdr
-
ehdr
)
; e_ehsize
dw
(
.segments.load
-
.segments
.dynamic
)
; e_phentsize
dw
(
phdr.load
-
phdr
.dynamic
)
; e_phentsize
%ifdef USE_NX
%ifdef USE_NX
%error "USE_NX not supported yet on i386 ('GOT' still needs RWX, and alignment has to be fixed)"
%error "USE_NX not supported yet on i386 ('GOT' still needs RWX, and alignment has to be fixed)"
;%ifdef USE_INTERP
;%ifdef USE_INTERP
...
@@ -47,41 +47,45 @@ header:
...
@@ -47,41 +47,45 @@ header:
; dd (PHDR_R | PHDR_W)
; dd (PHDR_R | PHDR_W)
; dd 0x1;000
; dd 0x1;000
%else
%else
.segments
:
phdr
:
%endif
%endif
%ifdef USE_INTERP
%ifdef USE_INTERP
.segments
.interp:
phdr
.interp:
dd
PT_INTERP
; {e_phnum: 2, e_shentsize: 0}, p_type
dd
PT_INTERP
; {e_phnum: 2, e_shentsize: 0}, p_type
dd
(
.
interp
-
header
)
; {e_shnum: <junk>, e_shstrnd: <junk>}, p_offset
dd
(
interp
-
ehdr
)
; {e_shnum: <junk>, e_shstrnd: <junk>}, p_offset
dd
.
interp
,
.
interp
; p_vaddr, p_paddr
dd
interp
,
interp
; p_vaddr, p_paddr
dd
(
.
interp.end
-
.
interp
)
; p_filesz
dd
(
interp.end
-
interp
)
; p_filesz
dd
(
.
interp.end
-
.
interp
)
; p_memsz
dd
(
interp.end
-
interp
)
; p_memsz
dd
0
,
0
; p_flags, p_align
dd
0
,
0
; p_flags, p_align
%endif
%endif
.segments
.dynamic:
phdr
.dynamic:
dd
PT_DYNAMIC
; {e_phnum: 2, e_shentsize: 0}, p_type
dd
PT_DYNAMIC
; {e_phnum: 2, e_shentsize: 0}, p_type
dd
(
dynamic
-
header
)
; {e_shnum: <junk>, e_shstrnd: <junk>}, p_offset
dd
(
dynamic
-
ehdr
)
; {e_shnum: <junk>, e_shstrnd: <junk>}, p_offset
dd
dynamic
,
0
; p_vaddr, p_paddr
dd
dynamic
,
0
; p_vaddr, p_paddr
dd
(
dynamic.end
-
dynamic
)
; p_filesz
dd
(
dynamic.end
-
dynamic
)
; p_filesz
dd
(
dynamic.end
-
dynamic
)
; p_memsz
dd
(
dynamic.end
-
dynamic
)
; p_memsz
dd
0
,
0
; p_flags, p_align
dd
0
,
0
; p_flags, p_align
%ifndef USE_NX
%ifndef USE_NX
.segments
.load:
phdr
.load:
dd
PT_LOAD
; p_type: 1 = PT_LOAD
dd
PT_LOAD
; p_type: 1 = PT_LOAD
dd
0
; p_offset
dd
0
; p_offset
dd
_smol_origin
,
0
; p_vaddr, p_paddr
dd
ehdr
,
0
; p_vaddr, p_paddr
; use memsize twice here, linux doesn't care and it compresses better
; use memsize twice here, linux doesn't care and it compresses better
dd
_smol_total_memsize
; p_filesz
dd
_smol_total_memsize
; p_filesz
dd
_smol_total_memsize
; p_memsz
dd
_smol_total_memsize
; p_memsz
dd
(
PHDR_R
|
PHDR_W
|
PHDR_X
)
; p_flags
dd
(
PHDR_R
|
PHDR_W
|
PHDR_X
)
; p_flags
dd
0x1000
; p_align
dd
0x1000
; p_align
%endif
%endif
.segments.end:
phdr.end:
%ifdef USE_INTERP
%ifdef USE_INTERP
.interp:
[
section
.rodata.interp
]
interp:
db
"
/
lib
/
ld
-
linux.so.2
"
,
0
db
"
/
lib
/
ld
-
linux.so.2
"
,
0
.
interp.end:
interp.end:
%endif
%endif
[
section
.rodata.dynamic
]
global
_DYNAMIC
global
_DYNAMIC
_DYNAMIC:
_DYNAMIC:
dynamic:
dynamic:
...
@@ -93,6 +97,7 @@ dynamic.symtab:
...
@@ -93,6 +97,7 @@ dynamic.symtab:
dd
DT_SYMTAB
; d_tag: 6 = DT_SYMTAB
dd
DT_SYMTAB
; d_tag: 6 = DT_SYMTAB
dd
0
; d_un.d_ptr
dd
0
; d_un.d_ptr
%ifdef USE_DT_DEBUG
%ifdef USE_DT_DEBUG
dynamic.debug:
dd
DT_DEBUG
dd
DT_DEBUG
_DEBUG:
_DEBUG:
dd
0
dd
0
...
...
src/loader32.asm
View file @
c75be623
; vim: set ft=nasm t
s=8
:
; vim: set ft=nasm
e
t:
%include "rtld.inc"
%include "rtld.inc"
...
@@ -13,29 +13,124 @@
...
@@ -13,29 +13,124 @@
_smol_start:
_smol_start:
%ifdef USE_DL_FINI
%ifdef USE_DL_FINI
push
edx
; _dl_fini
push
edx
; _dl_fini
%endif
%endif
; try to get the 'version-agnostic' pffset of the stuff we're
; try to get the 'version-agnostic' pffset of the stuff we're
; interested in
; interested in
%ifdef USE_DT_DEBUG
%ifdef USE_DT_DEBUG
mov
eax
,
[
rel
_DEBUG
]
mov
eax
,
[
rel
_DEBUG
]
mov
eax
,
[
eax
+
4
]
mov
eax
,
[
eax
+
4
]
%endif
%endif
%ifdef SKIP_ENTRIES
%ifdef SKIP_ENTRIES
mov
eax
,
[
eax
+
LM_NEXT_OFFSET
]
; skip this binary
mov
eax
,
[
eax
+
LM_NEXT_OFFSET
]
; skip this binary
mov
eax
,
[
eax
+
LM_NEXT_OFFSET
]
; skip the vdso
;
mov eax, [eax + LM_NEXT_OFFSET] ; skip the vdso
%endif
%endif
push
_symbols
push
eax
%ifdef USE_DNLOAD_LOADER
pop
ebp
pop
edi
.next_hash:
mov
ecx
,
[
edi
]
; assume it's nonzero
push
ebp
pop
edx
; edx: hash
; ebx: link_map* chain
.next_link:
; pop edx
mov
edx
,
[
edx
+
L_NEXT_OFF
]
; ElfW(Dyn)* dyn(esi) = ebx->l_ld
mov
esi
,
[
edx
+
L_LD_OFF
]
push
edx
; get strtab off
.next_dyn:
lodsd
cmp
al
,
DT_STRTAB
lodsd
jne
short
.next_dyn
; void* addr(edx) = ebx->l_addr
; const char* strtab(ebx)=lookup(esi,DT_STRTAB);
mov
edx
,
[
edx
+
L_ADDR_OFF
]
cmp
eax
,
edx
jae
short
.noreldynaddr
add
eax
,
edx
.noreldynaddr:
push
eax
pop
ebx
; const ElfW(Sym)* symtab(edx) = lookup(esi, DT_SYMTAB);
lodsd
; SYMTAB d_tag
lodsd
; SYMTAB d_un
cmp
eax
,
edx
jae
short
.norelsymaddr
add
eax
,
edx
.norelsymaddr:
push
eax
pop
edx
.next_sym:
mov
esi
,
[
edx
+
ST_NAME_OFF
]
add
esi
,
ebx
push
ecx
push
ebx
push
33
push
5381
pop
eax
pop
ebx
xor
ecx
,
ecx
.nexthashiter:
xchg
eax
,
ecx
lodsb
or
al
,
al
xchg
eax
,
ecx
jz
short
.breakhash
push
edx
mul
ebx
pop
edx
add
eax
,
ecx
jmp
short
.nexthashiter
.breakhash:
pop
ebx
pop
ecx
cmp
ecx
,
eax
je
short
.hasheq
add
edx
,
SYMTAB_SIZE
cmp
edx
,
ebx
jb
short
.next_sym
pop
edx
jmp
short
.next_link
.hasheq:
mov
eax
,
[
edx
+
ST_VALUE_OFF
]
pop
edx
mov
esi
,
[
edx
+
L_ADDR_OFF
]
;cmp eax, esi
; jb short .hasheqnorel
add
eax
,
esi
.hasheqnorel:
;add eax, [edx + L_ADDR_OFF] ; TODO: CONDITIONAL!
stosd
%ifdef USE_JMP_BYTES
inc
edi
; skip 0xE9 (jmp) offset
%endif
cmp
word
[
edi
],
0
jne
short
.next_hash
; if USE_DNLOAD_LOADER
%else
mov
ebx
,
eax
mov
ebx
,
eax
; mov esi, eax
;.looper:
; lodsd
; cmp dword eax, _smol_start
; jne short .looper
; sub esi, ebx
; sub esi, LM_ENTRY_OFFSET_BASE+4 ; +4: take inc-after from lodsd into acct
mov
edi
,
eax
mov
edi
,
eax
push
-
1
push
-
1
pop
ecx
pop
ecx
...
@@ -140,6 +235,8 @@ link: ; (struct link_map *root, char *symtable)
...
@@ -140,6 +235,8 @@ link: ; (struct link_map *root, char *symtable)
jmp
short
link.do_symbols
jmp
short
link.do_symbols
inc
esi
inc
esi
link.done:
link.done:
; if USE_DNLOAD_LOADER ... else ...
%endif
;xor ebp, ebp ; let's put that burden on the user code, so they can leave
;xor ebp, ebp ; let's put that burden on the user code, so they can leave
; it out if they want to
; it out if they want to
...
@@ -147,10 +244,15 @@ link.done:
...
@@ -147,10 +244,15 @@ link.done:
%ifdef USE_DL_FINI
%ifdef USE_DL_FINI
pop
edx
; _dl_fini
pop
edx
; _dl_fini
%endif
%endif
sub
esp
,
20
; put the stack where _start (C code) expects it to be
; move esp into eax, *then* increase the stack by 4, as main()
; this can't be left out, because X needs the envvars
; expects a return address to be inserted by a call instruction
; (which we don't have, so we're doing a 1-byte fixup instead of a
; 5-byte call)
push
esp
pop
eax
push
eax
push
eax
;.loopme: jmp short .loopme
;jmp short _start
;jmp short _start
; by abusing the linker script, _start ends up right here :)
; by abusing the linker script, _start ends up right here :)
src/loader64.asm
View file @
c75be623
...
@@ -69,22 +69,22 @@ _smol_start:
...
@@ -69,22 +69,22 @@ _smol_start:
jne
short
.next_dyn
jne
short
.next_dyn
; void* addr(rcx) = r12->l_addr
; void* addr(rcx) = r12->l_addr
; const char* strtab(r
9) =
lookup(rsi,DT_STRTAB),
*symtab_end(r
8
)=r
9
;
; const char* strtab(r
8)=
lookup(rsi,DT_STRTAB)
/*
,*symtab_end(r
9
)=r
8*/
;
mov
rcx
,
[
r12
+
L_ADDR_OFF
]
mov
rcx
,
[
r12
+
L_ADDR_OFF
]
cmp
rax
,
rcx
cmp
rax
,
rcx
j
g
e
short
.noreldynaddr
j
a
e
short
.noreldynaddr
add
rax
,
rcx
add
rax
,
rcx