ELF: amd64-linux main programs use 2-step de-compressor

The first $ARCH to move to 2-step de-compressor for ELF main programs.
De-compressor uses memfd_create to comply with strictest SELinux
settings (no PROT_WRITE on any PROT_EXEC page).
First step de-compressor always uses NRV2B to de-compress the second step,
and the second step can use a different de-compressor for each PT_LOAD.
	modified:   p_lx_elf.cpp
	modified:   stub/Makefile
	modified:   stub/src/amd64-linux.elf-fold.lds
	modified:   stub/src/amd64-linux.elf-entry.S
	modified:   stub/src/amd64-linux.elf-fold.S
	new file:   stub/src/amd64-linux.elf-main2.c

	modified:   stub/amd64-linux.elf-entry.h
	modified:   stub/amd64-linux.elf-fold.h
	modified:   stub/tmp/amd64-linux.elf-entry.bin.dump
	modified:   stub/tmp/amd64-linux.elf-fold.map
This commit is contained in:
John Reiser 2024-06-21 10:43:47 -07:00
parent 44e4bd0b54
commit c36977f0b1
10 changed files with 2547 additions and 1153 deletions

View File

@ -1466,7 +1466,7 @@ PackLinuxElf32::buildLinuxLoader(
// EXP_TAIL FIXME: unfilter
// SO_TAIL
// SO_MAIN C-language supervision based on PT_LOADs
char sec[120];
char sec[120]; memset(sec, 0, sizeof(sec)); // debug convenience
int len = 0;
unsigned m_decompr = (methods_used ? methods_used : (1u << ph_forced_method(ph.method)));
len += snprintf(sec, sizeof(sec), "%s", "SO_HEAD,ptr_NEXT,EXP_HEAD");
@ -1494,8 +1494,44 @@ PackLinuxElf32::buildLinuxLoader(
method = M_NRV2B_LE32; // requires unaligned fetch
if (this->e_machine==Elf32_Ehdr::EM_ARM)
method = M_NRV2B_8; //only ARM v6 and above has unaligned fetch
} // end shlib
else if (0
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_386
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_MIPS
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_PPC
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_ARM
) { // main program with ELF2 de-compressor
initLoader(fold, szfold);
char sec[120];
int len = 0;
unsigned m_decompr = (methods_used ? methods_used : (1u << ph_forced_method(ph.method)));
len += snprintf(sec, sizeof(sec), "%s", ".text,EXP_HEAD");
if (((1u<<M_NRV2B_LE32)|(1u<<M_NRV2B_8)|(1u<<M_NRV2B_LE16)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "NRV2B");
}
if (((1u<<M_NRV2D_LE32)|(1u<<M_NRV2D_8)|(1u<<M_NRV2D_LE16)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "NRV2D");
}
if (((1u<<M_NRV2E_LE32)|(1u<<M_NRV2E_8)|(1u<<M_NRV2E_LE16)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "NRV2E");
}
if (((1u<<M_LZMA)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "LZMA_ELF00,LZMA_DEC20,LZMA_DEC30");
}
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "SYSCALLS,EXP_TAIL");
(void)len;
addLoader(sec, nullptr);
relocateLoader();
{
int sz_unc_int;
uncLoader = linker->getLoader(&sz_unc_int);
sz_unc = sz_unc_int;
}
method = M_NRV2B_LE32; // requires unaligned fetch
if (this->e_machine==Elf32_Ehdr::EM_ARM)
method = M_NRV2B_8; //only ARM v6 and above has unaligned fetch
}
else {
else { // main program with ELF1 de-compressor
cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
unsigned fold_hdrlen = upx::umax(0x80u, usizeof(hf->ehdr) +
get_te16(&hf->ehdr.e_phentsize) * get_te16(&hf->ehdr.e_phnum) +
@ -1529,16 +1565,28 @@ PackLinuxElf32::buildLinuxLoader(
initLoader(proto, szproto, -1, sz_cpr);
NO_printf("FOLDEXEC unc=%#x cpr=%#x\n", sz_unc, sz_cpr);
linker->addSection("FOLDEXEC", mb_cprLoader, sizeof(b_info) + sz_cpr, 0);
if (xct_off
&& ( this->e_machine==Elf32_Ehdr::EM_ARM
if (xct_off // shlib
&& (0
|| this->e_machine==Elf32_Ehdr::EM_ARM
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_MIPS
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_PPC
|| this->e_machine==Elf32_Ehdr::EM_386)
) {
) { // shlib with ELF2 de-compressor
addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR");
}
else {
else if (0
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_ARM
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_MIPS
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_PPC
//ELF2 NYI || this->e_machine==Elf32_Ehdr::EM_386
) { // main program with ELF2 de-compressor
addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR");
defineSymbols(ft);
}
else { // ELF1 de-compressor
addStubEntrySections(ft, (methods_used ? methods_used
: (1u << ph_forced_method(ph.method))) );
if (!xct_off) {
if (!xct_off) { // main program
defineSymbols(ft);
}
}
@ -1601,7 +1649,40 @@ PackLinuxElf64::buildLinuxLoader(
}
method = M_NRV2B_LE32; // requires unaligned fetch
}
else {
else if (0
|| this->e_machine==Elf64_Ehdr::EM_X86_64
//ELF2 NYI || this->e_machine==Elf64_Ehdr::EM_PPC64
//ELF2 NYI || this->e_machine==Elf64_Ehdr::EM_AARCH64
) { // main program with ELF2 de-compressor
initLoader(fold, szfold);
char sec[120]; memset(sec, 0, sizeof(sec)); // debug convenience
int len = 0;
unsigned m_decompr = (methods_used ? methods_used : (1u << ph_forced_method(ph.method)));
len += snprintf(sec, sizeof(sec), "%s", ".text,EXP_HEAD");
if (((1u<<M_NRV2B_LE32)|(1u<<M_NRV2B_8)|(1u<<M_NRV2B_LE16)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "NRV2B");
}
if (((1u<<M_NRV2D_LE32)|(1u<<M_NRV2D_8)|(1u<<M_NRV2D_LE16)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "NRV2D");
}
if (((1u<<M_NRV2E_LE32)|(1u<<M_NRV2E_8)|(1u<<M_NRV2E_LE16)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "NRV2E");
}
if (((1u<<M_LZMA)) & m_decompr) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "LZMA_ELF00,LZMA_DEC20,LZMA_DEC30");
}
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "SYSCALLS,EXP_TAIL");
(void)len;
addLoader(sec, nullptr);
relocateLoader();
{
int sz_unc_int;
uncLoader = linker->getLoader(&sz_unc_int);
sz_unc = sz_unc_int;
}
method = M_NRV2B_LE32; // requires unaligned fetch
}
else { // not shlib: main program with ELF1 de-compressor
cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
unsigned fold_hdrlen = upx::umax(0x80u, usizeof(hf->ehdr) +
get_te16(&hf->ehdr.e_phentsize) * get_te16(&hf->ehdr.e_phnum) +
@ -1630,18 +1711,34 @@ PackLinuxElf64::buildLinuxLoader(
set_te32(&h.sz_cpr, h.sz_cpr);
set_te32(&h.sz_unc, h.sz_unc);
memcpy(cprLoader, &h, sizeof(h)); // cprLoader will become FOLDEXEC
}
} // end (0 < szfold)
initLoader(proto, szproto, -1, sz_cpr);
NO_printf("FOLDEXEC unc=%#x cpr=%#x\n", sz_unc, sz_cpr);
linker->addSection("FOLDEXEC", mb_cprLoader, sizeof(b_info) + sz_cpr, 0);
if (xct_off
&& ( this->e_machine==Elf64_Ehdr::EM_X86_64
&& (0
|| this->e_machine==Elf64_Ehdr::EM_X86_64
//ELF2 NYI || this->e_machine==Elf64_Ehdr::EM_PPC64
|| this->e_machine==Elf64_Ehdr::EM_AARCH64)
) {
addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR");
} // shlib
else if (0
|| this->e_machine==Elf64_Ehdr::EM_X86_64
//ELF2 NYI || this->e_machine==Elf64_Ehdr::EM_PPC64
//ELF2 NYI || this->e_machine==Elf64_Ehdr::EM_AARCH64
) { // main program with ELF2 de-compressor
addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR");
if (this->e_machine==Elf64_Ehdr::EM_PPC64
&& elfout.ehdr.e_ident[Elf64_Ehdr::EI_DATA]==Elf64_Ehdr::ELFDATA2MSB) {
addLoader("ELFMAINZe");
}
if (!xct_off) {
defineSymbols(ft);
}
}
else {
else { // main program with ELF1 de-compressor
addStubEntrySections(ft, (methods_used ? methods_used
: (1u << ph_forced_method(ph.method))) );
if (!xct_off) {
@ -3460,10 +3557,24 @@ PackLinuxElf32::generateElfHdr(
cprElfHdr2 *const h2 = (cprElfHdr2 *)(void *)&elfout;
cprElfHdr3 *const h3 = (cprElfHdr3 *)(void *)&elfout;
h3->ehdr = ((cprElfHdr3 const *)proto)->ehdr;
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
if (Elf32_Ehdr::ET_REL == get_te16(&h3->ehdr.e_type)) {
set_te32(&h3->ehdr.e_phoff, sizeof(Elf32_Ehdr));
set_te16(&h3->ehdr.e_ehsize,sizeof(Elf32_Ehdr));
set_te16(&h3->ehdr.e_phentsize, sizeof(Elf32_Phdr));
set_te16(&h3->ehdr.e_phnum, 2);
memset(&h3->phdr[C_BASE], 0, sizeof(h3->phdr[C_BASE]));
memset(&h3->phdr[C_TEXT], 0, sizeof(h3->phdr[C_TEXT]));
memset(&h3->phdr[2 ], 0, sizeof(h3->phdr[2 ]));
set_te32(&h3->phdr[C_BASE].p_flags, 0);
set_te32(&h3->phdr[C_TEXT].p_flags, Elf32_Phdr::PF_X| Elf32_Phdr::PF_R);
}
else {
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
}
h3->ehdr.e_type = ehdri.e_type; // ET_EXEC vs ET_DYN (gcc -pie -fPIC)
memset(&h3->linfo, 0, sizeof(h3->linfo));
h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = ei_osabi;
if (Elf32_Ehdr::EM_MIPS==e_machine) { // MIPS R3000 FIXME
h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = Elf32_Ehdr::ELFOSABI_NONE;
@ -3749,8 +3860,22 @@ PackLinuxElf64::generateElfHdr(
cprElfHdr2 *const h2 = (cprElfHdr2 *)(void *)&elfout;
cprElfHdr3 *const h3 = (cprElfHdr3 *)(void *)&elfout;
h3->ehdr = ((cprElfHdr3 const *)proto)->ehdr;
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
if (Elf64_Ehdr::ET_REL == get_te16(&h3->ehdr.e_type)) {
set_te64(&h3->ehdr.e_phoff, sizeof(Elf64_Ehdr));
set_te16(&h3->ehdr.e_ehsize,sizeof(Elf64_Ehdr));
set_te16(&h3->ehdr.e_phentsize, sizeof(Elf64_Phdr));
set_te16(&h3->ehdr.e_phnum, 2);
memset(&h3->phdr[C_BASE], 0, sizeof(h3->phdr[C_BASE]));
memset(&h3->phdr[C_TEXT], 0, sizeof(h3->phdr[C_TEXT]));
memset(&h3->phdr[2 ], 0, sizeof(h3->phdr[2 ]));
set_te32(&h3->phdr[C_BASE].p_flags, 0);
set_te32(&h3->phdr[C_TEXT].p_flags, Elf64_Phdr::PF_X| Elf64_Phdr::PF_R);
}
else {
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
}
memset(&h3->linfo, 0, sizeof(h3->linfo));
h3->ehdr.e_type = ehdri.e_type; // ET_EXEC vs ET_DYN (gcc -pie -fPIC)
h3->ehdr.e_ident[Elf64_Ehdr::EI_OSABI] = ei_osabi;
@ -3774,13 +3899,27 @@ PackLinuxElf64::generateElfHdr(
h2->ehdr.e_shstrndx = o_elf_shnum - 1;
}
else {
// https://bugzilla.redhat.com/show_bug.cgi?id=2131609
// 0==.e_shnum is a special case for libbfd
// that requires 0==.e_shentsize in order to force "no Shdrs"
h2->ehdr.e_shentsize = 0;
h2->ehdr.e_shnum = 0;
h2->ehdr.e_shstrndx = 0;
}
unsigned phnum_o = 2 + n_phdrx; // C_BASE, C_TEXT
unsigned const phnum_i = get_te16(&h2->ehdr.e_phnum);
unsigned phnum_o = 2 + n_phdrx; // C_BASE, C_TEXT
set_te16(&h2->ehdr.e_phnum, phnum_o);
o_binfo = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr)*phnum_o + sizeof(l_info) + sizeof(p_info);
set_te64(&h2->phdr[C_TEXT].p_filesz, sizeof(*h2)); // + identsize;
h2->phdr[C_TEXT].p_memsz = h2->phdr[C_TEXT].p_filesz;
set_te32(&h2->phdr[C_TEXT].p_type, PT_LOAD64); // be sure
for (unsigned j=0; j < phnum_i; ++j) {
if (is_LOAD64(&h3->phdr[j])) {
set_te64( &h3->phdr[j].p_align, page_size);
}
}
// Info for OS kernel to set the brk()
if (brka) {

View File

@ -313,6 +313,37 @@ define tc.default.f-embed_objinfo_without_xstrip
cat $1.dump >> $1
endef
define tc.default.f-embed_objinfo_without_xstrip_keep_dot_text
chmod a-x $1
$(call tc,objcopy) -R .data -R .bss $1
$(call tc,objcopy) -R .comment -R .note -R .note.GNU-stack -R .reginfo $1
$(call tc,objcopy) --strip-unneeded --keep-symbol=_start --keep-symbol=upx_so_main $1
#
# Disassemble for human readability
# objdump
# -Dr disassemble-all, with interspersed relocations
$(call tc,objdump) -Dr $(tc_objdump_disasm_options) $1 | $(RTRIM) > $1.disasm
#
# Disassemble for post-processing by buildLinuxLoader()
# objdump
# -r reloc
# -h section-headers
# -t syms
# -w (wide) do not truncate symbol names
# sed
# remove filename from first line
# change tab to space
# collapse multiple leading zeroes
# remove everything after "CONTENTS"
$(call tc,objdump) -htr -w $1 | $(BLSQUEEZE) | sed \
-e '1s/^.*: *file format/file format/' \
-e 's/$(tab)/ /g' \
-e 's/ 00*/ 0/g' \
-e 's/CONTENTS.*/CONTENTS/' \
> $1.dump
cat $1.dump >> $1
endef
tc.default.f-objstrip-disasm.bin = @true
tc.default.f-objstrip-disasm.o = $(call tc,objdump) -dr $(tc_objdump_disasm_options) $1 | $(RTRIM) > $1.disasm
tc.default.f-objstrip-disasm.obj = $(call tc,objdump) -dr $(tc_objdump_disasm_options) $1 | $(RTRIM) > $1.disasm
@ -395,12 +426,13 @@ amd64-linux.elf-so_entry.h: $(srcdir)/src/$$T.S
$(call tc,f-embed_objinfo,tmp/$T.bin)
$(call tc,bin2h) tmp/$T.bin $@
amd64-linux.elf-fold.h : tmp/$$T.o tmp/amd64-linux.elf-main.o $(srcdir)/src/$$T.lds tmp/amd64-expand.o
# # FIXME: multiarch-ld-2.18 creates a huge file here, so use 2.17
# ####$(call tc,ld) --strip-all -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
multiarch-ld-2.17 --strip-all -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
$(call tc,f-objstrip,tmp/$T.bin)
$(call tc,sstrip) tmp/$T.bin
amd64-linux.elf-fold.h : $(srcdir)/src/$$T.lds \
tmp/$$T.o \
tmp/amd64-expand.o \
tmp/amd64-linux.elf-main2.o
# FIXME: multiarch-ld-2.18 creates a huge file here, so use 2.17
multiarch-ld-2.17 -r -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
$(call tc,f-embed_objinfo_without_xstrip_keep_dot_text,tmp/$T.bin)
$(call tc,bin2h) tmp/$T.bin $@
amd64-linux.elf-so_fold.h : tmp/$$T.o tmp/amd64-linux.elf-so_main.o $(srcdir)/src/$$T.lds tmp/amd64-expand.o
@ -424,6 +456,10 @@ tmp/amd64-linux.elf-main.o : $(srcdir)/src/$$T.c
$(call tc,gcc) -c -Os $< -o $@
$(call tc,f-objstrip,$@)
tmp/amd64-linux.elf-main2.o : $(srcdir)/src/$$T.c
$(call tc,gcc) -c -Os $< -o $@
$(call tc,f-objstrip,$@)
tmp/amd64-linux.elf-so_main.o : $(srcdir)/src/$$T.c
$(call tc,gcc) -c -O $< -o $@
$(call tc,objcopy) --rename-section .text=SO_MAIN -R .comment -R .note -R .note.GNU-stack -R .reginfo $@

View File

@ -1,5 +1,5 @@
/* amd64-linux.elf-entry.h
created from amd64-linux.elf-entry.bin, 8461 (0x210d) bytes
created from amd64-linux.elf-entry.bin, 1101 (0x44d) bytes
This file is part of the UPX executable compressor.
@ -32,538 +32,78 @@
/* clang-format off */
#define STUB_AMD64_LINUX_ELF_ENTRY_SIZE 8461
#define STUB_AMD64_LINUX_ELF_ENTRY_ADLER32 0x9242c38c
#define STUB_AMD64_LINUX_ELF_ENTRY_CRC32 0x7b043db7
#define STUB_AMD64_LINUX_ELF_ENTRY_SIZE 1101
#define STUB_AMD64_LINUX_ELF_ENTRY_ADLER32 0x64b93a03
#define STUB_AMD64_LINUX_ELF_ENTRY_CRC32 0x33613c50
unsigned char stub_amd64_linux_elf_entry[8461] = {
unsigned char stub_amd64_linux_elf_entry[1101] = {
/* 0x0000 */ 127, 69, 76, 70, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x0010 */ 1, 0, 62, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x0020 */ 0, 0, 0, 0, 0, 0, 0, 0,120, 24, 0, 0, 0, 0, 0, 0,
/* 0x0020 */ 0, 0, 0, 0, 0, 0, 0, 0,232, 1, 0, 0, 0, 0, 0, 0,
/* 0x0030 */ 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0,
/* 0x0040 */ 80, 82,232, 0, 0, 0, 0, 85, 83, 81, 82, 72, 1,254, 86, 72,
/* 0x0050 */ 41,254, 72,137,254, 72,137,215, 49,219, 49,201, 72,131,205,255,
/* 0x0060 */ 232, 80, 0, 0, 0, 1,219,116, 2,243,195,139, 30, 72,131,238,
/* 0x0070 */ 252, 17,219,138, 22,243,195, 72,141, 4, 47,131,249, 5,138, 16,
/* 0x0080 */ 118, 33, 72,131,253,252,119, 27,131,233, 4,139, 16, 72,131,192,
/* 0x0090 */ 4,131,233, 4,137, 23, 72,141,127, 4,115,239,131,193, 4,138,
/* 0x00a0 */ 16,116, 16, 72,255,192,136, 23,131,233, 1,138, 16, 72,141,127,
/* 0x00b0 */ 1,117,240,243,195,252, 65, 91, 65,128,248, 8, 15,133,174, 0,
/* 0x00c0 */ 0, 0,235, 8, 72,255,198,136, 23, 72,255,199,138, 22, 1,219,
/* 0x00d0 */ 117, 10,139, 30, 72,131,238,252, 17,219,138, 22,114,230,141, 65,
/* 0x00e0 */ 1,235, 7,255,200, 65,255,211, 17,192, 65,255,211, 17,192, 1,
/* 0x00f0 */ 219,117, 10,139, 30, 72,131,238,252, 17,219,138, 22,115,228,131,
/* 0x0100 */ 232, 3,114, 29,193,224, 8, 15,182,210, 9,208, 72,255,198,131,
/* 0x0110 */ 240,255, 15,132, 0, 0, 0, 0,209,248, 72, 99,232,114, 56,235,
/* 0x0120 */ 14, 1,219,117, 8,139, 30, 72,131,238,252, 17,219,114, 40,255,
/* 0x0130 */ 193, 1,219,117, 8,139, 30, 72,131,238,252, 17,219,114, 24, 65,
/* 0x0140 */ 255,211, 17,201, 1,219,117, 8,139, 30, 72,131,238,252, 17,219,
/* 0x0150 */ 115,237,131,193, 2,235, 5, 65,255,211, 17,201, 72,129,253, 0,
/* 0x0160 */ 251,255,255,131,209, 2,232, 0, 0, 0, 0,233, 92,255,255,255,
/* 0x0170 */ 87, 94, 65,128,248, 5, 15,133,149, 0, 0, 0,235, 8, 72,255,
/* 0x0180 */ 198,136, 23, 72,255,199,138, 22, 1,219,117, 10,139, 30, 72,131,
/* 0x0190 */ 238,252, 17,219,138, 22,114,230,141, 65, 1,235, 7,255,200, 65,
/* 0x01a0 */ 255,211, 17,192, 65,255,211, 17,192, 1,219,117, 10,139, 30, 72,
/* 0x01b0 */ 131,238,252, 17,219,138, 22,115,228,131,232, 3,114, 27,193,224,
/* 0x01c0 */ 8, 15,182,210, 9,208, 72,255,198,131,240,255, 15,132, 0, 0,
/* 0x01d0 */ 0, 0,209,248, 72, 99,232,235, 3, 65,255,211, 17,201, 65,255,
/* 0x01e0 */ 211, 17,201,117, 24,255,193, 65,255,211, 17,201, 1,219,117, 8,
/* 0x01f0 */ 139, 30, 72,131,238,252, 17,219,115,237,131,193, 2, 72,129,253,
/* 0x0200 */ 0,251,255,255,131,209, 1,232, 0, 0, 0, 0,233,117,255,255,
/* 0x0210 */ 255, 87, 94, 65,128,248, 2, 15,133,135, 0, 0, 0,235, 8, 72,
/* 0x0220 */ 255,198,136, 23, 72,255,199,138, 22, 1,219,117, 10,139, 30, 72,
/* 0x0230 */ 131,238,252, 17,219,138, 22,114,230,141, 65, 1, 65,255,211, 17,
/* 0x0240 */ 192, 1,219,117, 10,139, 30, 72,131,238,252, 17,219,138, 22,115,
/* 0x0250 */ 235,131,232, 3,114, 23,193,224, 8, 15,182,210, 9,208, 72,255,
/* 0x0260 */ 198,131,240,255, 15,132, 0, 0, 0, 0, 72, 99,232,141, 65, 1,
/* 0x0270 */ 65,255,211, 17,201, 65,255,211, 17,201,117, 24,137,193,131,192,
/* 0x0280 */ 2, 65,255,211, 17,201, 1,219,117, 8,139, 30, 72,131,238,252,
/* 0x0290 */ 17,219,115,237, 72,129,253, 0,243,255,255, 17,193,232, 0, 0,
/* 0x02a0 */ 0, 0,235,131, 87, 94, 65,128,248, 14, 15,133, 0, 0, 0, 0,
/* 0x02b0 */ 85, 72,137,229, 68,139, 9, 73,137,208, 72,137,242, 72,141,119,
/* 0x02c0 */ 2, 86,138, 7,255,202,136,193, 36, 7,192,233, 3, 72,199,195,
/* 0x02d0 */ 0,253,255,255, 72,211,227,136,193, 72,141,156, 92,136,241,255,
/* 0x02e0 */ 255, 72,131,227,192,106, 0, 72, 57,220,117,249, 83, 72,141,123,
/* 0x02f0 */ 8,138, 78,255,255,202,136, 71, 2,136,200,192,233, 4,136, 79,
/* 0x0300 */ 1, 36, 15,136, 7, 72,141, 79,252, 80, 65, 87, 72,141, 71, 4,
/* 0x0310 */ 69, 49,255, 65, 86, 65,190, 1, 0, 0, 0, 65, 85, 69, 49,237,
/* 0x0320 */ 65, 84, 85, 83, 72,137, 76, 36,240, 72,137, 68, 36,216,184, 1,
/* 0x0330 */ 0, 0, 0, 72,137,116, 36,248, 76,137, 68, 36,232,137,195, 68,
/* 0x0340 */ 137, 76, 36,228, 15,182, 79, 2,211,227,137,217, 72,139, 92, 36,
/* 0x0350 */ 56,255,201,137, 76, 36,212, 15,182, 79, 1,211,224, 72,139, 76,
/* 0x0360 */ 36,240,255,200,137, 68, 36,208, 15,182, 7,199, 1, 0, 0, 0,
/* 0x0370 */ 0,199, 68, 36,200, 0, 0, 0, 0,199, 68, 36,196, 1, 0, 0,
/* 0x0380 */ 0,199, 68, 36,192, 1, 0, 0, 0,199, 68, 36,188, 1, 0, 0,
/* 0x0390 */ 0,199, 3, 0, 0, 0, 0,137, 68, 36,204, 15,182, 79, 1, 1,
/* 0x03a0 */ 193,184, 0, 3, 0, 0,211,224, 49,201,141,184, 54, 7, 0, 0,
/* 0x03b0 */ 65, 57,255,115, 19, 72,139, 92, 36,216,137,200,255,193, 57,249,
/* 0x03c0 */ 102,199, 4, 67, 0, 4,235,235, 72,139,124, 36,248,137,208, 69,
/* 0x03d0 */ 49,210, 65,131,203,255, 49,210, 73,137,252, 73, 1,196, 76, 57,
/* 0x03e0 */ 231, 15,132,239, 8, 0, 0, 15,182, 7, 65,193,226, 8,255,194,
/* 0x03f0 */ 72,255,199, 65, 9,194,131,250, 4,126,227, 68, 59,124, 36,228,
/* 0x0400 */ 15,131,218, 8, 0, 0,139, 68, 36,212, 72, 99, 92, 36,200, 72,
/* 0x0410 */ 139, 84, 36,216, 68, 33,248,137, 68, 36,184, 72, 99,108, 36,184,
/* 0x0420 */ 72,137,216, 72,193,224, 4, 72, 1,232, 65,129,251,255,255,255,
/* 0x0430 */ 0, 76,141, 12, 66,119, 26, 76, 57,231, 15,132,150, 8, 0, 0,
/* 0x0440 */ 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,
/* 0x0450 */ 194, 65, 15,183, 17, 68,137,216,193,232, 11, 15,183,202, 15,175,
/* 0x0460 */ 193, 65, 57,194, 15,131,197, 1, 0, 0, 65,137,195,184, 0, 8,
/* 0x0470 */ 0, 0, 72,139, 92, 36,216, 41,200, 15,182, 76, 36,204,190, 1,
/* 0x0480 */ 0, 0, 0,193,248, 5,141, 4, 2, 65, 15,182,213,102, 65,137,
/* 0x0490 */ 1,139, 68, 36,208, 68, 33,248,211,224,185, 8, 0, 0, 0, 43,
/* 0x04a0 */ 76, 36,204,211,250, 1,208,105,192, 0, 3, 0, 0,131,124, 36,
/* 0x04b0 */ 200, 6,137,192, 76,141,140, 67,108, 14, 0, 0, 15,142,184, 0,
/* 0x04c0 */ 0, 0, 72,139, 84, 36,232, 68,137,248, 68, 41,240, 15,182, 44,
/* 0x04d0 */ 2, 1,237, 72, 99,214,137,235,129,227, 0, 1, 0, 0, 65,129,
/* 0x04e0 */ 251,255,255,255, 0, 72, 99,195, 73,141, 4, 65, 76,141, 4, 80,
/* 0x04f0 */ 119, 26, 76, 57,231, 15,132,219, 7, 0, 0, 15,182, 7, 65,193,
/* 0x0500 */ 226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 65, 15,183,144,
/* 0x0510 */ 0, 2, 0, 0, 68,137,216,193,232, 11, 15,183,202, 15,175,193,
/* 0x0520 */ 65, 57,194,115, 32, 65,137,195,184, 0, 8, 0, 0, 1,246, 41,
/* 0x0530 */ 200,193,248, 5,133,219,141, 4, 2,102, 65,137,128, 0, 2, 0,
/* 0x0540 */ 0,116, 33,235, 45, 65, 41,195, 65, 41,194,137,208,102,193,232,
/* 0x0550 */ 5,141,116, 54, 1,102, 41,194,133,219,102, 65,137,144, 0, 2,
/* 0x0560 */ 0, 0,116, 14,129,254,255, 0, 0, 0, 15,142, 97,255,255,255,
/* 0x0570 */ 235,120,129,254,255, 0, 0, 0,127,112, 72, 99,198, 65,129,251,
/* 0x0580 */ 255,255,255, 0, 77,141, 4, 65,119, 26, 76, 57,231, 15,132, 67,
/* 0x0590 */ 7, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,
/* 0x05a0 */ 199, 65, 9,194, 65, 15,183, 16, 68,137,216,193,232, 11, 15,183,
/* 0x05b0 */ 202, 15,175,193, 65, 57,194,115, 24, 65,137,195,184, 0, 8, 0,
/* 0x05c0 */ 0, 1,246, 41,200,193,248, 5,141, 4, 2,102, 65,137, 0,235,
/* 0x05d0 */ 161, 65, 41,195, 65, 41,194,137,208,102,193,232, 5,141,116, 54,
/* 0x05e0 */ 1,102, 41,194,102, 65,137, 16,235,136, 72,139, 76, 36,232, 68,
/* 0x05f0 */ 137,248, 65,255,199, 65,137,245, 64,136, 52, 1,131,124, 36,200,
/* 0x0600 */ 3,127, 13,199, 68, 36,200, 0, 0, 0, 0,233,166, 6, 0, 0,
/* 0x0610 */ 139, 84, 36,200,139, 68, 36,200,131,234, 3,131,232, 6,131,124,
/* 0x0620 */ 36,200, 9, 15, 79,208,137, 84, 36,200,233,135, 6, 0, 0, 65,
/* 0x0630 */ 41,195, 65, 41,194,137,208,102,193,232, 5,102, 41,194, 72,139,
/* 0x0640 */ 68, 36,216, 65,129,251,255,255,255, 0,102, 65,137, 17, 72,141,
/* 0x0650 */ 52, 88,119, 26, 76, 57,231, 15,132,121, 6, 0, 0, 15,182, 7,
/* 0x0660 */ 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 15,183,
/* 0x0670 */ 150,128, 1, 0, 0, 68,137,216,193,232, 11, 15,183,202, 15,175,
/* 0x0680 */ 193, 65, 57,194,115, 78, 65,137,195,184, 0, 8, 0, 0, 76,139,
/* 0x0690 */ 76, 36,216, 41,200,139, 76, 36,196, 68,137,116, 36,196,193,248,
/* 0x06a0 */ 5,141, 4, 2,139, 84, 36,192,137, 76, 36,192,102,137,134,128,
/* 0x06b0 */ 1, 0, 0, 49,192,131,124, 36,200, 6,137, 84, 36,188, 15,159,
/* 0x06c0 */ 192, 73,129,193,100, 6, 0, 0,141, 4, 64,137, 68, 36,200,233,
/* 0x06d0 */ 84, 2, 0, 0, 65, 41,195, 65, 41,194,137,208,102,193,232, 5,
/* 0x06e0 */ 102, 41,194, 65,129,251,255,255,255, 0,102,137,150,128, 1, 0,
/* 0x06f0 */ 0,119, 26, 76, 57,231, 15,132,218, 5, 0, 0, 15,182, 7, 65,
/* 0x0700 */ 193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 15,183,150,
/* 0x0710 */ 152, 1, 0, 0, 68,137,216,193,232, 11, 15,183,202, 15,175,193,
/* 0x0720 */ 65, 57,194, 15,131,208, 0, 0, 0, 65,184, 0, 8, 0, 0, 65,
/* 0x0730 */ 137,195, 72,193,227, 5, 68,137,192, 41,200,193,248, 5,141, 4,
/* 0x0740 */ 2,102,137,134,152, 1, 0, 0, 72,139, 68, 36,216, 72, 1,216,
/* 0x0750 */ 65,129,251,255,255,255, 0, 72,141, 52,104,119, 26, 76, 57,231,
/* 0x0760 */ 15,132,112, 5, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227,
/* 0x0770 */ 8, 72,255,199, 65, 9,194, 15,183,150,224, 1, 0, 0, 68,137,
/* 0x0780 */ 216,193,232, 11, 15,183,202, 15,175,193, 65, 57,194,115, 79, 65,
/* 0x0790 */ 41,200, 65,137,195, 65,193,248, 5, 69,133,255, 66,141, 4, 2,
/* 0x07a0 */ 102,137,134,224, 1, 0, 0, 15,132, 41, 5, 0, 0, 49,192,131,
/* 0x07b0 */ 124, 36,200, 6, 72,139, 92, 36,232, 15,159,192,141, 68, 0, 9,
/* 0x07c0 */ 137, 68, 36,200, 68,137,248, 68, 41,240, 68, 15,182, 44, 3, 68,
/* 0x07d0 */ 137,248, 65,255,199, 68,136, 44, 3,233,216, 4, 0, 0, 65, 41,
/* 0x07e0 */ 195, 65, 41,194,137,208,102,193,232, 5,102, 41,194,102,137,150,
/* 0x07f0 */ 224, 1, 0, 0,233, 17, 1, 0, 0, 65, 41,195, 65, 41,194,137,
/* 0x0800 */ 208,102,193,232, 5,102, 41,194, 65,129,251,255,255,255, 0,102,
/* 0x0810 */ 137,150,152, 1, 0, 0,119, 26, 76, 57,231, 15,132,181, 4, 0,
/* 0x0820 */ 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,199, 65,
/* 0x0830 */ 9,194, 15,183,150,176, 1, 0, 0, 68,137,216,193,232, 11, 15,
/* 0x0840 */ 183,202, 15,175,193, 65, 57,194,115, 32, 65,137,195,184, 0, 8,
/* 0x0850 */ 0, 0, 41,200,193,248, 5,141, 4, 2,102,137,134,176, 1, 0,
/* 0x0860 */ 0,139, 68, 36,196,233,152, 0, 0, 0, 65, 41,195, 65, 41,194,
/* 0x0870 */ 137,208,102,193,232, 5,102, 41,194, 65,129,251,255,255,255, 0,
/* 0x0880 */ 102,137,150,176, 1, 0, 0,119, 26, 76, 57,231, 15,132, 68, 4,
/* 0x0890 */ 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,199,
/* 0x08a0 */ 65, 9,194, 15,183,150,200, 1, 0, 0, 68,137,216,193,232, 11,
/* 0x08b0 */ 15,183,202, 15,175,193, 65, 57,194,115, 29, 65,137,195,184, 0,
/* 0x08c0 */ 8, 0, 0, 41,200,193,248, 5,141, 4, 2,102,137,134,200, 1,
/* 0x08d0 */ 0, 0,139, 68, 36,192,235, 34, 65, 41,195, 65, 41,194,137,208,
/* 0x08e0 */ 102,193,232, 5,102, 41,194,139, 68, 36,188,102,137,150,200, 1,
/* 0x08f0 */ 0, 0,139, 84, 36,192,137, 84, 36,188,139, 76, 36,196,137, 76,
/* 0x0900 */ 36,192, 68,137,116, 36,196, 65,137,198, 49,192,131,124, 36,200,
/* 0x0910 */ 6, 76,139, 76, 36,216, 15,159,192, 73,129,193,104, 10, 0, 0,
/* 0x0920 */ 141, 68, 64, 8,137, 68, 36,200, 65,129,251,255,255,255, 0,119,
/* 0x0930 */ 26, 76, 57,231, 15,132,156, 3, 0, 0, 15,182, 7, 65,193,226,
/* 0x0940 */ 8, 65,193,227, 8, 72,255,199, 65, 9,194, 65, 15,183, 17, 68,
/* 0x0950 */ 137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,194,115, 39,
/* 0x0960 */ 65,137,195,184, 0, 8, 0, 0, 69, 49,237, 41,200,193,248, 5,
/* 0x0970 */ 141, 4, 2,102, 65,137, 1, 72, 99, 68, 36,184, 72,193,224, 4,
/* 0x0980 */ 77,141, 68, 1, 4,235,120, 65, 41,195, 65, 41,194,137,208,102,
/* 0x0990 */ 193,232, 5,102, 41,194, 65,129,251,255,255,255, 0,102, 65,137,
/* 0x09a0 */ 17,119, 26, 76, 57,231, 15,132, 42, 3, 0, 0, 15,182, 7, 65,
/* 0x09b0 */ 193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 65, 15,183,
/* 0x09c0 */ 81, 2, 68,137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,
/* 0x09d0 */ 194,115, 52, 65,137,195,184, 0, 8, 0, 0, 65,189, 8, 0, 0,
/* 0x09e0 */ 0, 41,200,193,248, 5,141, 4, 2,102, 65,137, 65, 2, 72, 99,
/* 0x09f0 */ 68, 36,184, 72,193,224, 4, 77,141,132, 1, 4, 1, 0, 0, 65,
/* 0x0a00 */ 185, 3, 0, 0, 0,235, 39, 65, 41,195, 65, 41,194,137,208,102,
/* 0x0a10 */ 193,232, 5, 77,141,129, 4, 2, 0, 0, 65,189, 16, 0, 0, 0,
/* 0x0a20 */ 102, 41,194,102, 65,137, 81, 2, 65,185, 8, 0, 0, 0, 68,137,
/* 0x0a30 */ 203,189, 1, 0, 0, 0, 72, 99,197, 65,129,251,255,255,255, 0,
/* 0x0a40 */ 73,141, 52, 64,119, 26, 76, 57,231, 15,132,135, 2, 0, 0, 15,
/* 0x0a50 */ 182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194,
/* 0x0a60 */ 15,183, 14, 68,137,216,193,232, 11, 15,183,209, 15,175,194, 65,
/* 0x0a70 */ 57,194,115, 23, 65,137,195,184, 0, 8, 0, 0, 1,237, 41,208,
/* 0x0a80 */ 193,248, 5,141, 4, 1,102,137, 6,235, 22, 65, 41,195, 65, 41,
/* 0x0a90 */ 194,137,200,102,193,232, 5,141,108, 45, 1,102, 41,193,102,137,
/* 0x0aa0 */ 14,255,203,117,145,184, 1, 0, 0, 0, 68,137,201,211,224, 41,
/* 0x0ab0 */ 197, 68, 1,237,131,124, 36,200, 3, 15,143,194, 1, 0, 0,131,
/* 0x0ac0 */ 68, 36,200, 7,184, 3, 0, 0, 0,131,253, 4, 15, 76,197, 72,
/* 0x0ad0 */ 139, 92, 36,216, 65,184, 1, 0, 0, 0, 72,152, 72,193,224, 7,
/* 0x0ae0 */ 76,141,140, 3, 96, 3, 0, 0,187, 6, 0, 0, 0, 73, 99,192,
/* 0x0af0 */ 65,129,251,255,255,255, 0, 73,141, 52, 65,119, 26, 76, 57,231,
/* 0x0b00 */ 15,132,208, 1, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227,
/* 0x0b10 */ 8, 72,255,199, 65, 9,194, 15,183, 22, 68,137,216,193,232, 11,
/* 0x0b20 */ 15,183,202, 15,175,193, 65, 57,194,115, 24, 65,137,195,184, 0,
/* 0x0b30 */ 8, 0, 0, 69, 1,192, 41,200,193,248, 5,141, 4, 2,102,137,
/* 0x0b40 */ 6,235, 23, 65, 41,195, 65, 41,194,137,208,102,193,232, 5, 71,
/* 0x0b50 */ 141, 68, 0, 1,102, 41,194,102,137, 22,255,203,117,143, 65,131,
/* 0x0b60 */ 232, 64, 65,131,248, 3, 69,137,198, 15,142, 13, 1, 0, 0, 65,
/* 0x0b70 */ 131,230, 1, 68,137,192,209,248, 65,131,206, 2, 65,131,248, 13,
/* 0x0b80 */ 141,112,255,127, 35,137,241, 72,139, 92, 36,216, 73, 99,192, 65,
/* 0x0b90 */ 211,230, 72, 1,192, 68,137,242, 72,141, 20, 83, 72, 41,194, 76,
/* 0x0ba0 */ 141,138, 94, 5, 0, 0,235, 81,141,112,251, 65,129,251,255,255,
/* 0x0bb0 */ 255, 0,119, 26, 76, 57,231, 15,132, 25, 1, 0, 0, 15,182, 7,
/* 0x0bc0 */ 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 65,209,
/* 0x0bd0 */ 235, 69, 1,246, 69, 57,218,114, 7, 69, 41,218, 65,131,206, 1,
/* 0x0be0 */ 255,206,117,199, 76,139, 76, 36,216, 65,193,230, 4,190, 4, 0,
/* 0x0bf0 */ 0, 0, 73,129,193, 68, 6, 0, 0, 65,189, 1, 0, 0, 0,187,
/* 0x0c00 */ 1, 0, 0, 0, 72, 99,195, 65,129,251,255,255,255, 0, 77,141,
/* 0x0c10 */ 4, 65,119, 26, 76, 57,231, 15,132,185, 0, 0, 0, 15,182, 7,
/* 0x0c20 */ 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 65, 15,
/* 0x0c30 */ 183, 16, 68,137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,
/* 0x0c40 */ 194,115, 24, 65,137,195,184, 0, 8, 0, 0, 1,219, 41,200,193,
/* 0x0c50 */ 248, 5,141, 4, 2,102, 65,137, 0,235, 26, 65, 41,195, 65, 41,
/* 0x0c60 */ 194,137,208,102,193,232, 5,141, 92, 27, 1, 69, 9,238,102, 41,
/* 0x0c70 */ 194,102, 65,137, 16, 69, 1,237,255,206,117,136, 65,255,198,116,
/* 0x0c80 */ 64,131,197, 2, 69, 57,254,119, 77, 72,139, 84, 36,232, 68,137,
/* 0x0c90 */ 248, 68, 41,240, 68, 15,182, 44, 2, 68,137,248, 65,255,199,255,
/* 0x0ca0 */ 205, 68,136, 44, 2, 15,149,194, 49,192, 68, 59,124, 36,228, 15,
/* 0x0cb0 */ 146,192,133,194,117,211, 68, 59,124, 36,228, 15,130, 69,247,255,
/* 0x0cc0 */ 255, 65,129,251,255,255,255, 0,119, 22, 76, 57,231,184, 1, 0,
/* 0x0cd0 */ 0, 0,116, 35,235, 7,184, 1, 0, 0, 0,235, 26, 72,255,199,
/* 0x0ce0 */ 137,248, 43, 68, 36,248, 72,139, 76, 36,240, 72,139, 92, 36, 56,
/* 0x0cf0 */ 137, 1, 68,137, 59, 49,192, 91, 93, 65, 92, 65, 93, 65, 94, 65,
/* 0x0d00 */ 95, 65, 87, 72,141, 71, 4, 69, 49,255, 65, 86, 65,190, 1, 0,
/* 0x0d10 */ 0, 0, 65, 85, 69, 49,237, 65, 84, 85, 83, 72,137, 76, 36,240,
/* 0x0d20 */ 72,137, 68, 36,216,184, 1, 0, 0, 0, 72,137,116, 36,248, 76,
/* 0x0d30 */ 137, 68, 36,232,137,195, 68,137, 76, 36,228, 15,182, 79, 2,211,
/* 0x0d40 */ 227,137,217, 72,139, 92, 36, 56,255,201,137, 76, 36,212, 15,182,
/* 0x0d50 */ 79, 1,211,224, 72,139, 76, 36,240,255,200,137, 68, 36,208, 15,
/* 0x0d60 */ 182, 7,199, 1, 0, 0, 0, 0,199, 68, 36,200, 0, 0, 0, 0,
/* 0x0d70 */ 199, 68, 36,196, 1, 0, 0, 0,199, 68, 36,192, 1, 0, 0, 0,
/* 0x0d80 */ 199, 68, 36,188, 1, 0, 0, 0,199, 3, 0, 0, 0, 0,137, 68,
/* 0x0d90 */ 36,204, 15,182, 79, 1, 1,193,184, 0, 3, 0, 0,211,224, 49,
/* 0x0da0 */ 201,141,184, 54, 7, 0, 0, 65, 57,255,115, 19, 72,139, 92, 36,
/* 0x0db0 */ 216,137,200,255,193, 57,249,102,199, 4, 67, 0, 4,235,235, 72,
/* 0x0dc0 */ 139,124, 36,248,137,208, 69, 49,210, 65,131,203,255, 49,210, 73,
/* 0x0dd0 */ 137,252, 73, 1,196, 76, 57,231, 15,132,239, 8, 0, 0, 15,182,
/* 0x0de0 */ 7, 65,193,226, 8,255,194, 72,255,199, 65, 9,194,131,250, 4,
/* 0x0df0 */ 126,227, 68, 59,124, 36,228, 15,131,218, 8, 0, 0,139, 68, 36,
/* 0x0e00 */ 212, 72, 99, 92, 36,200, 72,139, 84, 36,216, 68, 33,248,137, 68,
/* 0x0e10 */ 36,184, 72, 99,108, 36,184, 72,137,216, 72,193,224, 4, 72, 1,
/* 0x0e20 */ 232, 65,129,251,255,255,255, 0, 76,141, 12, 66,119, 26, 76, 57,
/* 0x0e30 */ 231, 15,132,150, 8, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,
/* 0x0e40 */ 227, 8, 72,255,199, 65, 9,194, 65, 15,183, 17, 68,137,216,193,
/* 0x0e50 */ 232, 11, 15,183,202, 15,175,193, 65, 57,194, 15,131,197, 1, 0,
/* 0x0e60 */ 0, 65,137,195,184, 0, 8, 0, 0, 72,139, 92, 36,216, 41,200,
/* 0x0e70 */ 15,182, 76, 36,204,190, 1, 0, 0, 0,193,248, 5,141, 4, 2,
/* 0x0e80 */ 65, 15,182,213,102, 65,137, 1,139, 68, 36,208, 68, 33,248,211,
/* 0x0e90 */ 224,185, 8, 0, 0, 0, 43, 76, 36,204,211,250, 1,208,105,192,
/* 0x0ea0 */ 0, 3, 0, 0,131,124, 36,200, 6,137,192, 76,141,140, 67,108,
/* 0x0eb0 */ 14, 0, 0, 15,142,184, 0, 0, 0, 72,139, 84, 36,232, 68,137,
/* 0x0ec0 */ 248, 68, 41,240, 15,182, 44, 2, 1,237, 72, 99,214,137,235,129,
/* 0x0ed0 */ 227, 0, 1, 0, 0, 65,129,251,255,255,255, 0, 72, 99,195, 73,
/* 0x0ee0 */ 141, 4, 65, 76,141, 4, 80,119, 26, 76, 57,231, 15,132,219, 7,
/* 0x0ef0 */ 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,199,
/* 0x0f00 */ 65, 9,194, 65, 15,183,144, 0, 2, 0, 0, 68,137,216,193,232,
/* 0x0f10 */ 11, 15,183,202, 15,175,193, 65, 57,194,115, 32, 65,137,195,184,
/* 0x0f20 */ 0, 8, 0, 0, 1,246, 41,200,193,248, 5,133,219,141, 4, 2,
/* 0x0f30 */ 102, 65,137,128, 0, 2, 0, 0,116, 33,235, 45, 65, 41,195, 65,
/* 0x0f40 */ 41,194,137,208,102,193,232, 5,141,116, 54, 1,102, 41,194,133,
/* 0x0f50 */ 219,102, 65,137,144, 0, 2, 0, 0,116, 14,129,254,255, 0, 0,
/* 0x0f60 */ 0, 15,142, 97,255,255,255,235,120,129,254,255, 0, 0, 0,127,
/* 0x0f70 */ 112, 72, 99,198, 65,129,251,255,255,255, 0, 77,141, 4, 65,119,
/* 0x0f80 */ 26, 76, 57,231, 15,132, 67, 7, 0, 0, 15,182, 7, 65,193,226,
/* 0x0f90 */ 8, 65,193,227, 8, 72,255,199, 65, 9,194, 65, 15,183, 16, 68,
/* 0x0fa0 */ 137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,194,115, 24,
/* 0x0fb0 */ 65,137,195,184, 0, 8, 0, 0, 1,246, 41,200,193,248, 5,141,
/* 0x0fc0 */ 4, 2,102, 65,137, 0,235,161, 65, 41,195, 65, 41,194,137,208,
/* 0x0fd0 */ 102,193,232, 5,141,116, 54, 1,102, 41,194,102, 65,137, 16,235,
/* 0x0fe0 */ 136, 72,139, 76, 36,232, 68,137,248, 65,255,199, 65,137,245, 64,
/* 0x0ff0 */ 136, 52, 1,131,124, 36,200, 3,127, 13,199, 68, 36,200, 0, 0,
/* 0x1000 */ 0, 0,233,166, 6, 0, 0,139, 84, 36,200,139, 68, 36,200,131,
/* 0x1010 */ 234, 3,131,232, 6,131,124, 36,200, 9, 15, 79,208,137, 84, 36,
/* 0x1020 */ 200,233,135, 6, 0, 0, 65, 41,195, 65, 41,194,137,208,102,193,
/* 0x1030 */ 232, 5,102, 41,194, 72,139, 68, 36,216, 65,129,251,255,255,255,
/* 0x1040 */ 0,102, 65,137, 17, 72,141, 52, 88,119, 26, 76, 57,231, 15,132,
/* 0x1050 */ 121, 6, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,
/* 0x1060 */ 255,199, 65, 9,194, 15,183,150,128, 1, 0, 0, 68,137,216,193,
/* 0x1070 */ 232, 11, 15,183,202, 15,175,193, 65, 57,194,115, 78, 65,137,195,
/* 0x1080 */ 184, 0, 8, 0, 0, 76,139, 76, 36,216, 41,200,139, 76, 36,196,
/* 0x1090 */ 68,137,116, 36,196,193,248, 5,141, 4, 2,139, 84, 36,192,137,
/* 0x10a0 */ 76, 36,192,102,137,134,128, 1, 0, 0, 49,192,131,124, 36,200,
/* 0x10b0 */ 6,137, 84, 36,188, 15,159,192, 73,129,193,100, 6, 0, 0,141,
/* 0x10c0 */ 4, 64,137, 68, 36,200,233, 84, 2, 0, 0, 65, 41,195, 65, 41,
/* 0x10d0 */ 194,137,208,102,193,232, 5,102, 41,194, 65,129,251,255,255,255,
/* 0x10e0 */ 0,102,137,150,128, 1, 0, 0,119, 26, 76, 57,231, 15,132,218,
/* 0x10f0 */ 5, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,
/* 0x1100 */ 199, 65, 9,194, 15,183,150,152, 1, 0, 0, 68,137,216,193,232,
/* 0x1110 */ 11, 15,183,202, 15,175,193, 65, 57,194, 15,131,208, 0, 0, 0,
/* 0x1120 */ 65,184, 0, 8, 0, 0, 65,137,195, 72,193,227, 5, 68,137,192,
/* 0x1130 */ 41,200,193,248, 5,141, 4, 2,102,137,134,152, 1, 0, 0, 72,
/* 0x1140 */ 139, 68, 36,216, 72, 1,216, 65,129,251,255,255,255, 0, 72,141,
/* 0x1150 */ 52,104,119, 26, 76, 57,231, 15,132,112, 5, 0, 0, 15,182, 7,
/* 0x1160 */ 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 15,183,
/* 0x1170 */ 150,224, 1, 0, 0, 68,137,216,193,232, 11, 15,183,202, 15,175,
/* 0x1180 */ 193, 65, 57,194,115, 79, 65, 41,200, 65,137,195, 65,193,248, 5,
/* 0x1190 */ 69,133,255, 66,141, 4, 2,102,137,134,224, 1, 0, 0, 15,132,
/* 0x11a0 */ 41, 5, 0, 0, 49,192,131,124, 36,200, 6, 72,139, 92, 36,232,
/* 0x11b0 */ 15,159,192,141, 68, 0, 9,137, 68, 36,200, 68,137,248, 68, 41,
/* 0x11c0 */ 240, 68, 15,182, 44, 3, 68,137,248, 65,255,199, 68,136, 44, 3,
/* 0x11d0 */ 233,216, 4, 0, 0, 65, 41,195, 65, 41,194,137,208,102,193,232,
/* 0x11e0 */ 5,102, 41,194,102,137,150,224, 1, 0, 0,233, 17, 1, 0, 0,
/* 0x11f0 */ 65, 41,195, 65, 41,194,137,208,102,193,232, 5,102, 41,194, 65,
/* 0x1200 */ 129,251,255,255,255, 0,102,137,150,152, 1, 0, 0,119, 26, 76,
/* 0x1210 */ 57,231, 15,132,181, 4, 0, 0, 15,182, 7, 65,193,226, 8, 65,
/* 0x1220 */ 193,227, 8, 72,255,199, 65, 9,194, 15,183,150,176, 1, 0, 0,
/* 0x1230 */ 68,137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,194,115,
/* 0x1240 */ 32, 65,137,195,184, 0, 8, 0, 0, 41,200,193,248, 5,141, 4,
/* 0x1250 */ 2,102,137,134,176, 1, 0, 0,139, 68, 36,196,233,152, 0, 0,
/* 0x1260 */ 0, 65, 41,195, 65, 41,194,137,208,102,193,232, 5,102, 41,194,
/* 0x1270 */ 65,129,251,255,255,255, 0,102,137,150,176, 1, 0, 0,119, 26,
/* 0x1280 */ 76, 57,231, 15,132, 68, 4, 0, 0, 15,182, 7, 65,193,226, 8,
/* 0x1290 */ 65,193,227, 8, 72,255,199, 65, 9,194, 15,183,150,200, 1, 0,
/* 0x12a0 */ 0, 68,137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,194,
/* 0x12b0 */ 115, 29, 65,137,195,184, 0, 8, 0, 0, 41,200,193,248, 5,141,
/* 0x12c0 */ 4, 2,102,137,134,200, 1, 0, 0,139, 68, 36,192,235, 34, 65,
/* 0x12d0 */ 41,195, 65, 41,194,137,208,102,193,232, 5,102, 41,194,139, 68,
/* 0x12e0 */ 36,188,102,137,150,200, 1, 0, 0,139, 84, 36,192,137, 84, 36,
/* 0x12f0 */ 188,139, 76, 36,196,137, 76, 36,192, 68,137,116, 36,196, 65,137,
/* 0x1300 */ 198, 49,192,131,124, 36,200, 6, 76,139, 76, 36,216, 15,159,192,
/* 0x1310 */ 73,129,193,104, 10, 0, 0,141, 68, 64, 8,137, 68, 36,200, 65,
/* 0x1320 */ 129,251,255,255,255, 0,119, 26, 76, 57,231, 15,132,156, 3, 0,
/* 0x1330 */ 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,199, 65,
/* 0x1340 */ 9,194, 65, 15,183, 17, 68,137,216,193,232, 11, 15,183,202, 15,
/* 0x1350 */ 175,193, 65, 57,194,115, 39, 65,137,195,184, 0, 8, 0, 0, 69,
/* 0x1360 */ 49,237, 41,200,193,248, 5,141, 4, 2,102, 65,137, 1, 72, 99,
/* 0x1370 */ 68, 36,184, 72,193,224, 4, 77,141, 68, 1, 4,235,120, 65, 41,
/* 0x1380 */ 195, 65, 41,194,137,208,102,193,232, 5,102, 41,194, 65,129,251,
/* 0x1390 */ 255,255,255, 0,102, 65,137, 17,119, 26, 76, 57,231, 15,132, 42,
/* 0x13a0 */ 3, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,255,
/* 0x13b0 */ 199, 65, 9,194, 65, 15,183, 81, 2, 68,137,216,193,232, 11, 15,
/* 0x13c0 */ 183,202, 15,175,193, 65, 57,194,115, 52, 65,137,195,184, 0, 8,
/* 0x13d0 */ 0, 0, 65,189, 8, 0, 0, 0, 41,200,193,248, 5,141, 4, 2,
/* 0x13e0 */ 102, 65,137, 65, 2, 72, 99, 68, 36,184, 72,193,224, 4, 77,141,
/* 0x13f0 */ 132, 1, 4, 1, 0, 0, 65,185, 3, 0, 0, 0,235, 39, 65, 41,
/* 0x1400 */ 195, 65, 41,194,137,208,102,193,232, 5, 77,141,129, 4, 2, 0,
/* 0x1410 */ 0, 65,189, 16, 0, 0, 0,102, 41,194,102, 65,137, 81, 2, 65,
/* 0x1420 */ 185, 8, 0, 0, 0, 68,137,203,189, 1, 0, 0, 0, 72, 99,197,
/* 0x1430 */ 65,129,251,255,255,255, 0, 73,141, 52, 64,119, 26, 76, 57,231,
/* 0x1440 */ 15,132,135, 2, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227,
/* 0x1450 */ 8, 72,255,199, 65, 9,194, 15,183, 14, 68,137,216,193,232, 11,
/* 0x1460 */ 15,183,209, 15,175,194, 65, 57,194,115, 23, 65,137,195,184, 0,
/* 0x1470 */ 8, 0, 0, 1,237, 41,208,193,248, 5,141, 4, 1,102,137, 6,
/* 0x1480 */ 235, 22, 65, 41,195, 65, 41,194,137,200,102,193,232, 5,141,108,
/* 0x1490 */ 45, 1,102, 41,193,102,137, 14,255,203,117,145,184, 1, 0, 0,
/* 0x14a0 */ 0, 68,137,201,211,224, 41,197, 68, 1,237,131,124, 36,200, 3,
/* 0x14b0 */ 15,143,194, 1, 0, 0,131, 68, 36,200, 7,184, 3, 0, 0, 0,
/* 0x14c0 */ 131,253, 4, 15, 76,197, 72,139, 92, 36,216, 65,184, 1, 0, 0,
/* 0x14d0 */ 0, 72,152, 72,193,224, 7, 76,141,140, 3, 96, 3, 0, 0,187,
/* 0x14e0 */ 6, 0, 0, 0, 73, 99,192, 65,129,251,255,255,255, 0, 73,141,
/* 0x14f0 */ 52, 65,119, 26, 76, 57,231, 15,132,208, 1, 0, 0, 15,182, 7,
/* 0x1500 */ 65,193,226, 8, 65,193,227, 8, 72,255,199, 65, 9,194, 15,183,
/* 0x1510 */ 22, 68,137,216,193,232, 11, 15,183,202, 15,175,193, 65, 57,194,
/* 0x1520 */ 115, 24, 65,137,195,184, 0, 8, 0, 0, 69, 1,192, 41,200,193,
/* 0x1530 */ 248, 5,141, 4, 2,102,137, 6,235, 23, 65, 41,195, 65, 41,194,
/* 0x1540 */ 137,208,102,193,232, 5, 71,141, 68, 0, 1,102, 41,194,102,137,
/* 0x1550 */ 22,255,203,117,143, 65,131,232, 64, 65,131,248, 3, 69,137,198,
/* 0x1560 */ 15,142, 13, 1, 0, 0, 65,131,230, 1, 68,137,192,209,248, 65,
/* 0x1570 */ 131,206, 2, 65,131,248, 13,141,112,255,127, 35,137,241, 72,139,
/* 0x1580 */ 92, 36,216, 73, 99,192, 65,211,230, 72, 1,192, 68,137,242, 72,
/* 0x1590 */ 141, 20, 83, 72, 41,194, 76,141,138, 94, 5, 0, 0,235, 81,141,
/* 0x15a0 */ 112,251, 65,129,251,255,255,255, 0,119, 26, 76, 57,231, 15,132,
/* 0x15b0 */ 25, 1, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,
/* 0x15c0 */ 255,199, 65, 9,194, 65,209,235, 69, 1,246, 69, 57,218,114, 7,
/* 0x15d0 */ 69, 41,218, 65,131,206, 1,255,206,117,199, 76,139, 76, 36,216,
/* 0x15e0 */ 65,193,230, 4,190, 4, 0, 0, 0, 73,129,193, 68, 6, 0, 0,
/* 0x15f0 */ 65,189, 1, 0, 0, 0,187, 1, 0, 0, 0, 72, 99,195, 65,129,
/* 0x1600 */ 251,255,255,255, 0, 77,141, 4, 65,119, 26, 76, 57,231, 15,132,
/* 0x1610 */ 185, 0, 0, 0, 15,182, 7, 65,193,226, 8, 65,193,227, 8, 72,
/* 0x1620 */ 255,199, 65, 9,194, 65, 15,183, 16, 68,137,216,193,232, 11, 15,
/* 0x1630 */ 183,202, 15,175,193, 65, 57,194,115, 24, 65,137,195,184, 0, 8,
/* 0x1640 */ 0, 0, 1,219, 41,200,193,248, 5,141, 4, 2,102, 65,137, 0,
/* 0x1650 */ 235, 26, 65, 41,195, 65, 41,194,137,208,102,193,232, 5,141, 92,
/* 0x1660 */ 27, 1, 69, 9,238,102, 41,194,102, 65,137, 16, 69, 1,237,255,
/* 0x1670 */ 206,117,136, 65,255,198,116, 64,131,197, 2, 69, 57,254,119, 77,
/* 0x1680 */ 72,139, 84, 36,232, 68,137,248, 68, 41,240, 68, 15,182, 44, 2,
/* 0x1690 */ 68,137,248, 65,255,199,255,205, 68,136, 44, 2, 15,149,194, 49,
/* 0x16a0 */ 192, 68, 59,124, 36,228, 15,146,192,133,194,117,211, 68, 59,124,
/* 0x16b0 */ 36,228, 15,130, 69,247,255,255, 65,129,251,255,255,255, 0,119,
/* 0x16c0 */ 22, 76, 57,231,184, 1, 0, 0, 0,116, 35,235, 7,184, 1, 0,
/* 0x16d0 */ 0, 0,235, 26, 72,255,199,137,248, 43, 68, 36,248, 72,139, 76,
/* 0x16e0 */ 36,240, 72,139, 92, 36, 56,137, 1, 68,137, 59, 49,192, 91, 93,
/* 0x16f0 */ 65, 92, 65, 93, 65, 94, 65, 95, 72,139,117,248, 72,139,125, 16,
/* 0x1700 */ 139, 75, 4, 72, 1,206,139, 19, 72, 1,215,201,235, 2, 87, 94,
/* 0x1710 */ 89, 72,137,240, 72, 41,200, 90, 72, 41,215, 89,137, 57, 91, 93,
/* 0x1720 */ 195,104, 30, 0, 0, 0, 90,232, 30, 0, 0, 0, 80, 82, 79, 84,
/* 0x1730 */ 95, 69, 88, 69, 67,124, 80, 82, 79, 84, 95, 87, 82, 73, 84, 69,
/* 0x1740 */ 32,102, 97,105,108,101,100, 46, 10, 0, 94,106, 2, 95,106, 1,
/* 0x1750 */ 88, 15, 5,106,127, 95,106, 60, 88, 15, 5, 94,173,131,224,252,
/* 0x1760 */ 65,137,198, 86, 91,139, 22, 72,141,141,245,255,255,255, 68,139,
/* 0x1770 */ 57, 76, 41,249, 69, 41,247, 73, 1,206, 82, 80,106,255, 81, 77,
/* 0x1780 */ 41,201, 65,131,200,255,106, 34, 65, 90, 82, 94,106, 3, 90, 41,
/* 0x1790 */ 255,106, 9, 88, 15, 5, 72,137, 68, 36, 16, 80, 90, 83, 94,173,
/* 0x17a0 */ 80, 72,137,225, 73,137,213,173, 80,173, 65,144, 72,137,247, 94,
/* 0x17b0 */ 255,213, 89, 72,139,116, 36, 24, 72,139,124, 36, 16,106, 5, 90,
/* 0x17c0 */ 106, 10, 88, 15, 5, 65,255,229, 93,232,141,255,255,255, 0, 0,
/* 0x17d0 */ 0, 0,102,105,108,101, 32,102,111,114,109, 97,116, 32,101,108,
/* 0x17e0 */ 102, 54, 52, 45,120, 56, 54, 45, 54, 52, 10, 10, 83,101, 99,116,
/* 0x17f0 */ 105,111,110,115, 58, 10, 73,100,120, 32, 78, 97,109,101, 32, 32,
/* 0x1800 */ 32, 32, 32, 32, 32, 32, 32, 32, 83,105,122,101, 32, 32, 32, 32,
/* 0x1810 */ 32, 32, 86, 77, 65, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x1820 */ 32, 32, 32, 32, 76, 77, 65, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x1830 */ 32, 32, 32, 32, 32, 32, 70,105,108,101, 32,111,102,102, 32, 32,
/* 0x1840 */ 65,108,103,110, 32, 32, 70,108, 97,103,115, 10, 32, 32, 48, 32,
/* 0x1850 */ 69, 76, 70, 77, 65, 73, 78, 88, 32, 32, 32, 32, 32, 32, 48, 49,
/* 0x1860 */ 50, 32, 32, 48, 32, 32, 48, 32, 32, 48, 52, 48, 32, 32, 50, 42,
/* 0x1870 */ 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32, 32, 49,
/* 0x1880 */ 32, 78, 82, 86, 95, 72, 69, 65, 68, 32, 32, 32, 32, 32, 32, 48,
/* 0x1890 */ 54, 54, 32, 32, 48, 32, 32, 48, 32, 32, 48, 53, 50, 32, 32, 50,
/* 0x18a0 */ 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32, 32,
/* 0x18b0 */ 50, 32, 78, 82, 86, 50, 69, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x18c0 */ 48, 98, 97, 32, 32, 48, 32, 32, 48, 32, 32, 48, 98, 56, 32, 32,
/* 0x18d0 */ 50, 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32,
/* 0x18e0 */ 32, 51, 32, 78, 82, 86, 50, 68, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x18f0 */ 32, 48, 97, 49, 32, 32, 48, 32, 32, 48, 32, 32, 48, 49, 55, 50,
/* 0x1900 */ 32, 32, 50, 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83,
/* 0x1910 */ 10, 32, 32, 52, 32, 78, 82, 86, 50, 66, 32, 32, 32, 32, 32, 32,
/* 0x1920 */ 32, 32, 32, 48, 57, 51, 32, 32, 48, 32, 32, 48, 32, 32, 48, 50,
/* 0x1930 */ 49, 51, 32, 32, 50, 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78,
/* 0x1940 */ 84, 83, 10, 32, 32, 53, 32, 76, 90, 77, 65, 95, 69, 76, 70, 48,
/* 0x1950 */ 48, 32, 32, 32, 32, 48, 54, 52, 32, 32, 48, 32, 32, 48, 32, 32,
/* 0x1960 */ 48, 50, 97, 54, 32, 32, 50, 42, 42, 48, 32, 32, 67, 79, 78, 84,
/* 0x1970 */ 69, 78, 84, 83, 10, 32, 32, 54, 32, 76, 90, 77, 65, 95, 68, 69,
/* 0x1980 */ 67, 49, 48, 32, 32, 32, 32, 48, 57,102, 55, 32, 32, 48, 32, 32,
/* 0x1990 */ 48, 32, 32, 48, 51, 48, 97, 32, 32, 50, 42, 42, 48, 32, 32, 67,
/* 0x19a0 */ 79, 78, 84, 69, 78, 84, 83, 10, 32, 32, 55, 32, 76, 90, 77, 65,
/* 0x19b0 */ 95, 68, 69, 67, 50, 48, 32, 32, 32, 32, 48, 57,102, 55, 32, 32,
/* 0x19c0 */ 48, 32, 32, 48, 32, 32, 48,100, 48, 49, 32, 32, 50, 42, 42, 48,
/* 0x19d0 */ 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32, 32, 56, 32, 76,
/* 0x19e0 */ 90, 77, 65, 95, 68, 69, 67, 51, 48, 32, 32, 32, 32, 48, 49, 56,
/* 0x19f0 */ 32, 32, 48, 32, 32, 48, 32, 32, 48, 49, 54,102, 56, 32, 32, 50,
/* 0x1a00 */ 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32, 32,
/* 0x1a10 */ 57, 32, 78, 82, 86, 95, 84, 65, 73, 76, 32, 32, 32, 32, 32, 32,
/* 0x1a20 */ 48, 32, 32, 48, 32, 32, 48, 32, 32, 48, 49, 55, 49, 48, 32, 32,
/* 0x1a30 */ 50, 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32,
/* 0x1a40 */ 49, 48, 32, 69, 76, 70, 77, 65, 73, 78, 89, 32, 32, 32, 32, 32,
/* 0x1a50 */ 32, 48, 52, 98, 32, 32, 48, 32, 32, 48, 32, 32, 48, 49, 55, 49,
/* 0x1a60 */ 48, 32, 32, 50, 42, 42, 48, 32, 32, 67, 79, 78, 84, 69, 78, 84,
/* 0x1a70 */ 83, 10, 32, 49, 49, 32, 69, 76, 70, 77, 65, 73, 78, 90, 32, 32,
/* 0x1a80 */ 32, 32, 32, 32, 48, 55, 55, 32, 32, 48, 32, 32, 48, 32, 32, 48,
/* 0x1a90 */ 49, 55, 53, 98, 32, 32, 50, 42, 42, 48, 32, 32, 67, 79, 78, 84,
/* 0x1aa0 */ 69, 78, 84, 83, 10, 83, 89, 77, 66, 79, 76, 32, 84, 65, 66, 76,
/* 0x1ab0 */ 69, 58, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1ac0 */ 48, 48, 48, 32,108, 32, 32, 32, 32,100, 32, 32, 78, 82, 86, 95,
/* 0x1ad0 */ 72, 69, 65, 68, 32, 48, 32, 78, 82, 86, 95, 72, 69, 65, 68, 10,
/* 0x1ae0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1af0 */ 32,108, 32, 32, 32, 32,100, 32, 32, 76, 90, 77, 65, 95, 68, 69,
/* 0x1b00 */ 67, 51, 48, 32, 48, 32, 76, 90, 77, 65, 95, 68, 69, 67, 51, 48,
/* 0x1b10 */ 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1b20 */ 48, 32,108, 32, 32, 32, 32,100, 32, 32, 69, 76, 70, 77, 65, 73,
/* 0x1b30 */ 78, 89, 32, 48, 32, 69, 76, 70, 77, 65, 73, 78, 89, 10, 48, 48,
/* 0x1b40 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,108,
/* 0x1b50 */ 32, 32, 32, 32,100, 32, 32, 69, 76, 70, 77, 65, 73, 78, 90, 32,
/* 0x1b60 */ 48, 32, 69, 76, 70, 77, 65, 73, 78, 90, 10, 48, 48, 48, 48, 48,
/* 0x1b70 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,108, 32, 32, 32,
/* 0x1b80 */ 32,100, 32, 32, 69, 76, 70, 77, 65, 73, 78, 88, 32, 48, 32, 69,
/* 0x1b90 */ 76, 70, 77, 65, 73, 78, 88, 10, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1ba0 */ 48, 48, 48, 48, 48, 48, 48, 48, 32,108, 32, 32, 32, 32,100, 32,
/* 0x1bb0 */ 32, 78, 82, 86, 50, 69, 32, 48, 32, 78, 82, 86, 50, 69, 10, 48,
/* 0x1bc0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,
/* 0x1bd0 */ 108, 32, 32, 32, 32,100, 32, 32, 78, 82, 86, 50, 68, 32, 48, 32,
/* 0x1be0 */ 78, 82, 86, 50, 68, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1bf0 */ 48, 48, 48, 48, 48, 48, 32,108, 32, 32, 32, 32,100, 32, 32, 78,
/* 0x1c00 */ 82, 86, 50, 66, 32, 48, 32, 78, 82, 86, 50, 66, 10, 48, 48, 48,
/* 0x1c10 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,108, 32,
/* 0x1c20 */ 32, 32, 32,100, 32, 32, 76, 90, 77, 65, 95, 69, 76, 70, 48, 48,
/* 0x1c30 */ 32, 48, 32, 76, 90, 77, 65, 95, 69, 76, 70, 48, 48, 10, 48, 48,
/* 0x1c40 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,108,
/* 0x1c50 */ 32, 32, 32, 32,100, 32, 32, 76, 90, 77, 65, 95, 68, 69, 67, 49,
/* 0x1c60 */ 48, 32, 48, 32, 76, 90, 77, 65, 95, 68, 69, 67, 49, 48, 10, 48,
/* 0x1c70 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,
/* 0x1c80 */ 108, 32, 32, 32, 32,100, 32, 32, 76, 90, 77, 65, 95, 68, 69, 67,
/* 0x1c90 */ 50, 48, 32, 48, 32, 76, 90, 77, 65, 95, 68, 69, 67, 50, 48, 10,
/* 0x1ca0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1cb0 */ 32,108, 32, 32, 32, 32,100, 32, 32, 78, 82, 86, 95, 84, 65, 73,
/* 0x1cc0 */ 76, 32, 48, 32, 78, 82, 86, 95, 84, 65, 73, 76, 10, 48, 48, 48,
/* 0x1cd0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,103, 32,
/* 0x1ce0 */ 32, 32, 32, 32, 32, 32, 69, 76, 70, 77, 65, 73, 78, 88, 32, 48,
/* 0x1cf0 */ 32, 95,115,116, 97,114,116, 10, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1d00 */ 48, 48, 48, 48, 48, 48, 48, 48, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x1d10 */ 32, 42, 85, 78, 68, 42, 32, 48, 32, 79, 95, 66, 73, 78, 70, 79,
/* 0x1d20 */ 10, 10, 82, 69, 76, 79, 67, 65, 84, 73, 79, 78, 32, 82, 69, 67,
/* 0x1d30 */ 79, 82, 68, 83, 32, 70, 79, 82, 32, 91, 69, 76, 70, 77, 65, 73,
/* 0x1d40 */ 78, 88, 93, 58, 10, 79, 70, 70, 83, 69, 84, 32, 32, 32, 32, 32,
/* 0x1d50 */ 32, 32, 32, 32, 32, 32, 84, 89, 80, 69, 32, 32, 32, 32, 32, 32,
/* 0x1d60 */ 32, 32, 32, 32, 32, 32, 32, 32, 86, 65, 76, 85, 69, 10, 48, 48,
/* 0x1d70 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 51, 32, 82,
/* 0x1d80 */ 95, 88, 56, 54, 95, 54, 52, 95, 80, 67, 51, 50, 32, 32, 32, 32,
/* 0x1d90 */ 32, 69, 76, 70, 77, 65, 73, 78, 90, 43, 48,120, 48, 48, 48, 48,
/* 0x1da0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 54, 57, 10, 10, 82, 69,
/* 0x1db0 */ 76, 79, 67, 65, 84, 73, 79, 78, 32, 82, 69, 67, 79, 82, 68, 83,
/* 0x1dc0 */ 32, 70, 79, 82, 32, 91, 78, 82, 86, 50, 69, 93, 58, 10, 79, 70,
/* 0x1dd0 */ 70, 83, 69, 84, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 84,
/* 0x1de0 */ 89, 80, 69, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x1df0 */ 32, 86, 65, 76, 85, 69, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1e00 */ 48, 48, 48, 48, 48, 97,102, 32, 82, 95, 88, 56, 54, 95, 54, 52,
/* 0x1e10 */ 95, 80, 67, 51, 50, 32, 32, 32, 32, 32, 78, 82, 86, 95, 72, 69,
/* 0x1e20 */ 65, 68, 43, 48,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1e30 */ 48, 48, 48, 50, 49, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1e40 */ 48, 48, 48, 48, 53, 99, 32, 82, 95, 88, 56, 54, 95, 54, 52, 95,
/* 0x1e50 */ 80, 67, 51, 50, 32, 32, 32, 32, 32, 69, 76, 70, 77, 65, 73, 78,
/* 0x1e60 */ 89, 43, 48,120,102,102,102,102,102,102,102,102,102,102,102,102,
/* 0x1e70 */ 102,102,102, 99, 10, 10, 82, 69, 76, 79, 67, 65, 84, 73, 79, 78,
/* 0x1e80 */ 32, 82, 69, 67, 79, 82, 68, 83, 32, 70, 79, 82, 32, 91, 78, 82,
/* 0x1e90 */ 86, 50, 68, 93, 58, 10, 79, 70, 70, 83, 69, 84, 32, 32, 32, 32,
/* 0x1ea0 */ 32, 32, 32, 32, 32, 32, 32, 84, 89, 80, 69, 32, 32, 32, 32, 32,
/* 0x1eb0 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 86, 65, 76, 85, 69, 10, 48,
/* 0x1ec0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 57, 54, 32,
/* 0x1ed0 */ 82, 95, 88, 56, 54, 95, 54, 52, 95, 80, 67, 51, 50, 32, 32, 32,
/* 0x1ee0 */ 32, 32, 78, 82, 86, 95, 72, 69, 65, 68, 43, 48,120, 48, 48, 48,
/* 0x1ef0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 50, 49, 10, 48, 48,
/* 0x1f00 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 53, 99, 32, 82,
/* 0x1f10 */ 95, 88, 56, 54, 95, 54, 52, 95, 80, 67, 51, 50, 32, 32, 32, 32,
/* 0x1f20 */ 32, 69, 76, 70, 77, 65, 73, 78, 89, 43, 48,120,102,102,102,102,
/* 0x1f30 */ 102,102,102,102,102,102,102,102,102,102,102, 99, 10, 10, 82, 69,
/* 0x1f40 */ 76, 79, 67, 65, 84, 73, 79, 78, 32, 82, 69, 67, 79, 82, 68, 83,
/* 0x1f50 */ 32, 70, 79, 82, 32, 91, 78, 82, 86, 50, 66, 93, 58, 10, 79, 70,
/* 0x1f60 */ 70, 83, 69, 84, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 84,
/* 0x1f70 */ 89, 80, 69, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x1f80 */ 32, 86, 65, 76, 85, 69, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1f90 */ 48, 48, 48, 48, 48, 56, 98, 32, 82, 95, 88, 56, 54, 95, 54, 52,
/* 0x1fa0 */ 95, 80, 67, 51, 50, 32, 32, 32, 32, 32, 78, 82, 86, 95, 72, 69,
/* 0x1fb0 */ 65, 68, 43, 48,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1fc0 */ 48, 48, 48, 50, 49, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x1fd0 */ 48, 48, 48, 48, 53, 51, 32, 82, 95, 88, 56, 54, 95, 54, 52, 95,
/* 0x1fe0 */ 80, 67, 51, 50, 32, 32, 32, 32, 32, 69, 76, 70, 77, 65, 73, 78,
/* 0x1ff0 */ 89, 43, 48,120,102,102,102,102,102,102,102,102,102,102,102,102,
/* 0x2000 */ 102,102,102, 99, 10, 10, 82, 69, 76, 79, 67, 65, 84, 73, 79, 78,
/* 0x2010 */ 32, 82, 69, 67, 79, 82, 68, 83, 32, 70, 79, 82, 32, 91, 76, 90,
/* 0x2020 */ 77, 65, 95, 69, 76, 70, 48, 48, 93, 58, 10, 79, 70, 70, 83, 69,
/* 0x2030 */ 84, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 84, 89, 80, 69,
/* 0x2040 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 86, 65,
/* 0x2050 */ 76, 85, 69, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x2060 */ 48, 48, 48, 54, 32, 82, 95, 88, 56, 54, 95, 54, 52, 95, 80, 67,
/* 0x2070 */ 51, 50, 32, 32, 32, 32, 32, 76, 90, 77, 65, 95, 68, 69, 67, 51,
/* 0x2080 */ 48, 43, 48,120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x2090 */ 48, 48, 49, 50, 10, 10, 82, 69, 76, 79, 67, 65, 84, 73, 79, 78,
/* 0x20a0 */ 32, 82, 69, 67, 79, 82, 68, 83, 32, 70, 79, 82, 32, 91, 69, 76,
/* 0x20b0 */ 70, 77, 65, 73, 78, 90, 93, 58, 10, 79, 70, 70, 83, 69, 84, 32,
/* 0x20c0 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 84, 89, 80, 69, 32, 32,
/* 0x20d0 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 86, 65, 76, 85,
/* 0x20e0 */ 69, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x20f0 */ 55, 51, 32, 82, 95, 88, 56, 54, 95, 54, 52, 95, 51, 50, 32, 32,
/* 0x2100 */ 32, 32, 32, 32, 32, 79, 95, 66, 73, 78, 70, 79, 10
/* 0x0040 */ 89, 84, 95, 81,232, 47, 1, 0, 0,232, 42, 1, 0, 0, 72,139,
/* 0x0050 */ 7, 72,139, 79, 8, 72,131,199, 16, 72,131,248, 6,116, 12, 72,
/* 0x0060 */ 199,193, 0, 16, 0, 0, 72,133,192,117,227, 72,247,217, 81, 82,
/* 0x0070 */ 104,117,112,120, 0, 84, 95, 41,246,184, 63, 1, 0, 0,232, 2,
/* 0x0080 */ 1, 0, 0, 73,137,196, 89, 72,141, 61,174,255,255,255,139, 15,
/* 0x0090 */ 72, 41,207, 72,141, 53, 0, 0, 0, 0,173,147, 65,137,221,173,
/* 0x00a0 */ 146,131,194, 16, 82,106,255, 87, 72, 41,217, 81, 72, 1,251, 83,
/* 0x00b0 */ 84, 93, 72, 41,212, 72,131,228,192, 84, 95,173, 80,173,102,131,
/* 0x00c0 */ 248, 2,116, 1,244, 88, 72, 1,240, 80, 85, 49,219, 49,201, 72,
/* 0x00d0 */ 141, 21,196, 0, 0, 0,106,255, 93,252,168,164,255,210,114,251,
/* 0x00e0 */ 141, 65, 1,255,210, 17,192,255,210,115,248,131,232, 3,114, 12,
/* 0x00f0 */ 193,224, 8,172,131,240,255,116, 47, 72, 99,232,141, 65, 1,255,
/* 0x0100 */ 210, 17,201,255,210, 17,201,117, 13,137,193,131,192, 2,255,210,
/* 0x0110 */ 17,201,255,210,115,248,129,253, 0,243,255,255, 17,193, 86, 72,
/* 0x0120 */ 141, 52, 47,243,164, 94,235,180, 93, 89, 72, 57,206,116, 1,244,
/* 0x0130 */ 72,139, 69, 48, 72,137, 4, 36, 72,139, 85, 32, 84, 94, 76,137,
/* 0x0140 */ 231,106, 1, 88,232, 60, 0, 0, 0, 85, 92, 69, 41,201, 77,137,
/* 0x0150 */ 224,106, 1, 65, 90, 82, 94,106, 5, 90, 41,255,106, 9, 88,232,
/* 0x0160 */ 33, 0, 0, 0, 80, 72,137, 69, 24, 65, 80, 95,106, 3, 88, 15,
/* 0x0170 */ 5, 88, 72,131,192, 8,255,224, 72,139, 7, 72,131,199, 8, 72,
/* 0x0180 */ 133,192,117,244,195, 80, 15, 5, 89, 72, 61, 0,240,255,255,114,
/* 0x0190 */ 1,244,195, 72,139, 60, 36,102,175,195, 1,219,116, 2,243,195,
/* 0x01a0 */ 139, 30, 72,131,238,252, 17,219,243,195, 0, 0, 0, 0, 0, 0,
/* 0x01b0 */ 102,105,108,101, 32,102,111,114,109, 97,116, 32,101,108,102, 54,
/* 0x01c0 */ 52, 45,120, 56, 54, 45, 54, 52, 10, 10, 83,101, 99,116,105,111,
/* 0x01d0 */ 110,115, 58, 10, 73,100,120, 32, 78, 97,109,101, 32, 32, 32, 32,
/* 0x01e0 */ 32, 32, 32, 32, 32, 32, 83,105,122,101, 32, 32, 32, 32, 32, 32,
/* 0x01f0 */ 86, 77, 65, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x0200 */ 32, 32, 76, 77, 65, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x0210 */ 32, 32, 32, 32, 70,105,108,101, 32,111,102,102, 32, 32, 65,108,
/* 0x0220 */ 103,110, 32, 32, 70,108, 97,103,115, 10, 32, 32, 48, 32, 69, 76,
/* 0x0230 */ 70, 77, 65, 73, 78, 88, 32, 32, 32, 32, 32, 32, 48, 49, 54, 97,
/* 0x0240 */ 32, 32, 48, 32, 32, 48, 32, 32, 48, 52, 48, 32, 32, 50, 42, 42,
/* 0x0250 */ 48, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 32, 32, 49, 32,
/* 0x0260 */ 69, 76, 70, 77, 65, 73, 78, 90, 32, 32, 32, 32, 32, 32, 48, 52,
/* 0x0270 */ 32, 32, 48, 32, 32, 48, 32, 32, 48, 49, 97, 99, 32, 32, 50, 42,
/* 0x0280 */ 42, 50, 32, 32, 67, 79, 78, 84, 69, 78, 84, 83, 10, 83, 89, 77,
/* 0x0290 */ 66, 79, 76, 32, 84, 65, 66, 76, 69, 58, 10, 48, 48, 48, 48, 48,
/* 0x02a0 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32,108, 32, 32, 32,
/* 0x02b0 */ 32,100, 32, 32, 69, 76, 70, 77, 65, 73, 78, 90, 32, 48, 32, 69,
/* 0x02c0 */ 76, 70, 77, 65, 73, 78, 90, 10, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x02d0 */ 48, 48, 48, 48, 48, 48, 48, 48, 32,108, 32, 32, 32, 32,100, 32,
/* 0x02e0 */ 32, 69, 76, 70, 77, 65, 73, 78, 88, 32, 48, 32, 69, 76, 70, 77,
/* 0x02f0 */ 65, 73, 78, 88, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x0300 */ 48, 48, 48, 48, 48, 32,103, 32, 32, 32, 32, 32, 32, 32, 69, 76,
/* 0x0310 */ 70, 77, 65, 73, 78, 88, 32, 48, 32, 95,115,116, 97,114,116, 10,
/* 0x0320 */ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x0330 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 42, 85, 78, 68, 42, 32, 48,
/* 0x0340 */ 32, 79, 95, 66, 73, 78, 70, 79, 10, 10, 82, 69, 76, 79, 67, 65,
/* 0x0350 */ 84, 73, 79, 78, 32, 82, 69, 67, 79, 82, 68, 83, 32, 70, 79, 82,
/* 0x0360 */ 32, 91, 69, 76, 70, 77, 65, 73, 78, 88, 93, 58, 10, 79, 70, 70,
/* 0x0370 */ 83, 69, 84, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 84, 89,
/* 0x0380 */ 80, 69, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
/* 0x0390 */ 86, 65, 76, 85, 69, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x03a0 */ 48, 48, 48, 48, 53, 54, 32, 82, 95, 88, 56, 54, 95, 54, 52, 95,
/* 0x03b0 */ 80, 67, 51, 50, 32, 32, 32, 32, 32, 69, 76, 70, 77, 65, 73, 78,
/* 0x03c0 */ 90, 43, 48,120,102,102,102,102,102,102,102,102,102,102,102,102,
/* 0x03d0 */ 102,102,102, 99, 10, 10, 82, 69, 76, 79, 67, 65, 84, 73, 79, 78,
/* 0x03e0 */ 32, 82, 69, 67, 79, 82, 68, 83, 32, 70, 79, 82, 32, 91, 69, 76,
/* 0x03f0 */ 70, 77, 65, 73, 78, 90, 93, 58, 10, 79, 70, 70, 83, 69, 84, 32,
/* 0x0400 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 84, 89, 80, 69, 32, 32,
/* 0x0410 */ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 86, 65, 76, 85,
/* 0x0420 */ 69, 10, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
/* 0x0430 */ 48, 48, 32, 82, 95, 88, 56, 54, 95, 54, 52, 95, 51, 50, 32, 32,
/* 0x0440 */ 32, 32, 32, 32, 32, 79, 95, 66, 73, 78, 70, 79, 10
};

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,20 @@
#include "arch/amd64/macros.S"
#include "arch/amd64/regs.h"
NBPW= 8
.macro jmps target
.byte 0xeb, \target - . - 1
.endm
/* These from /usr/include/unistd_64.h */
__NR_memfd_create= 319 // 0x13f
__NR_ftruncate= 77
__NR_exit= 60
__NR_mprotect= 10
__NR_mmap= 9
__NR_close= 3
__NR_open= 2
__NR_write= 1
sz_Ehdr= 64
e_phnum= 56
@ -46,10 +60,13 @@ sz_b_info= 12
sz_cpr= 4
b_method= 8
AT_PAGESZ= 6
PROT_READ= 1
PROT_WRITE= 2
PROT_EXEC= 4
MAP_SHARED= 1
MAP_PRIVATE= 2
MAP_FIXED= 0x10
MAP_ANONYMOUS= 0x20
@ -58,96 +75,207 @@ SYS_mmap= 9 // 64-bit mode only!
FD_stderr= 2
PAGE_SHIFT= 12
PAGE_MASK= (~0<<PAGE_SHIFT)
PAGE_SIZE= -PAGE_MASK
M_NRV2B_LE32=2 // ../conf.h
M_NRV2D_LE32=5
M_NRV2E_LE32=8
# low bits in O_BINFO
is_ptinterp= (1<<0)
unmap_all_pages= (1<<1)
// https://www.uclibc.org/docs/psABI-x86_64.pdf
section ELFMAINX
sz_pack2= .-4
_start: .globl _start
//// nop; int3 # uncomment for debugging
push %rax // space for entry address
push %rdx // register this function pointer with 'atexit'
call main // push &decompress
/* Returns 0 on success; non-zero on failure. */
f_exp: // shorter name
decompress: // (uchar const *src, size_t lsrc, uchar *dst, u32 &ldst, uint method)
pop %rcx // argc
push %rsp; pop %rdi // argv
push %rcx // argc
/* Arguments according to calling convention */
#define src %arg1
#define lsrc %arg2
#define dst %arg3
#define ldst %arg4 /* Out: actually a reference: &len_dst */
#define meth %arg5l
#define methb %arg5b
#define old_sp %rbp
F_FRAME= 7*NBPW
F_ENTR= 6*NBPW; F_PMASK= F_ENTR
F_RDX= 5*NBPW
F_LENU= 4*NBPW
F_ADRU= 3*NBPW
F_ELFA= 2*NBPW
F_LENX= 1*NBPW
F_ADRX= 0*NBPW
push %rbp; push %rbx // C callable
push ldst
push dst
addq src,lsrc; push lsrc // &input_eof
subq src,lsrc // restore the value of lsrc
D_FOLD= 1*NBPW // .data space at start of unfold
D_PMASK= 0*NBPW
section NRV_HEAD
AT_PAGESZ= 6 // /usr/include/elf.h
call zfind // skip argv
call zfind // skip env
0: // find AT_PAGESZ in auxv
mov (%rdi),%rax
mov NBPW(%rdi),%rcx; add $2*NBPW,%rdi
cmp $AT_PAGESZ,%rax; je 5f
mov $1<<12,%rcx // default PAGE_SIZE
test %rax,%rax; jne 0b
5:
neg %rcx; push %rcx // F_PMASK
push %rdx // F_RDX
// Create anonymous temporary file on mfd
push $'u'|('p'<<8)|('x'<<16)|(0<<24)
push %rsp; pop %arg1 // "upx"
subl %arg2l,%arg2l // 0
movl $__NR_memfd_create,%eax; call sys_check; mov %rax,%r12 // mfd
pop %rcx // discard "upx"
lea sz_pack2(%rip),%rdi
mov (%rdi),%ecx // sz_pack2: length before stub
sub %rcx,%rdi // elfaddr
lea o_binfo(%rip),%rsi
lodsl; xchg %eax,%ebx; mov %ebx,%r13d // O_BINFO; advance to &b_info
lodsl; xchg %eax,%edx; add $0x10,%edx; push %rdx // F_LENU = sz_unc + x86_overrun + insurance
push $-1 // space for F_ADRU
push %rdi // F_ELFA
sub %rbx,%rcx; push %rcx // F_LENX = sz_pack2 - O_BINFO
add %rdi,%rbx; push %rbx // F_ADRX = elfaddr + O_BINFO
push %rsp; pop old_sp
// alloca()
sub %rdx,%rsp // F_LENU space
CACHELINE= 8 * NBPW
and $-CACHELINE,%rsp // align
// Decompress the rest of this loader, and jump to it.
#define dst %rdi
#define src %rsi
#define lsrc %rcx
push %rsp; pop dst // dst= decompress onto stack
lodsl; push %rax // MATCH_11 .sz_cpr
lodsl; cmpw $M_NRV2B_LE32|(0<<8),%ax; je 0f; hlt; 0: // check method and filter bytes
pop %rax; add src,%rax; push %rax // MATCH_11 input_eof
push old_sp // MATCH_10
// This is nrv2b_d32, inlined and optimized for small space (about 160 bytes).
// The task is to de-compress the folded pieces for shared library init:
// the de-compressor(s) of the PT_LOAD pieces, and the C-code supervisor
// which adjusts the placement and mapping of the address space.
// The output length is a couple KB for NRV, a few KB for Lzma, 64KB for Zstd.
// This is motivated by the possibility of using multiple de-compressors
// depending on the characteristics of each PT_LOAD, and by the increased size
// and compressability of C-coded de-compressors for Lzma and Zstd
// in contrast to the simple and small assembly-coded NRV.
//%rsp:
// MATCH_10 old_sp
// MATCH_11 &input_eof
//%rbp === old_sp: array of F_FRAME
/* Working registers */
#define off %eax /* XXX: 2GB */
#define bits %ebx
#define len %ecx /* XXX: 2GB */
#define lenq %rcx
#define bits %ebx
#define displ %ebp
#define dispq %rbp
#define displ %ebp
movq src,%rsi // hardware src for movsb, lodsb
movq dst,%rdi // hardware dst for movsb
xor bits,bits // empty; force refill
xor len,len // create loop invariant
orq $(~0),dispq // -1: initial displacement
call setup // push &getbit [TUNED]
ra_setup:
/* AMD64 branch prediction is much worse if there are more than 3 branches
per 16-byte block. The jnextb would suffer unless inlined. getnextb is OK
using closed subroutine to save space, and should be OK on cycles because
CALL+RET should be predicted. getnextb could partially expand, using closed
subroutine only for refill.
*/
/* jump on next bit {0,1} with prediction {y==>likely, n==>unlikely} */
/* Prediction omitted for now. */
/* On refill: prefetch next byte, for latency reduction on literals and offsets. */
#define jnextb0np jnextb0yp
#define jnextb0yp GETBITp; jnc
#define jnextb1np jnextb1yp
#define jnextb1yp GETBITp; jc
#define GETBITp \
addl bits,bits; jnz 0f; \
movl (%rsi),bits; subq $-4,%rsi; \
adcl bits,bits; movb (%rsi),%dl; \
0:
/* Same, but without prefetch (not useful for length of match.) */
#define jnextb0n jnextb0y
#define jnextb0y GETBIT; jnc
#define jnextb1n jnextb1y
#define jnextb1y GETBIT; jc
#define GETBIT \
addl bits,bits; jnz 0f; \
movl (%rsi),bits; subq $-4,%rsi; \
adcl bits,bits; \
0:
#define GETBIT call *%rdx
#define jnextb0 GETBIT; jnc
#define jnextb1 GETBIT; jc
/* rotate next bit into bottom bit of reg */
#define getnextbp(reg) call *%r11; adcl reg,reg
#define getnextb(reg) getnextbp(reg)
#define getnextb(reg) GETBIT; adcl reg,reg
xor bits,bits // empty; force refill
xor len,len // create loop invariant
lea getbit(%rip),%rdx
push $-1; pop dispq // initial displacement
cld // paranoia
.byte 0xa8 // "testb $... ,%al" ==> "jmp top_n2b"
lit_n2b:
movsb // *dst++ = *src++;
top_n2b:
jnextb1 lit_n2b
lea 1(lenq),off # [len= 0] off= 1
offmore_n2b:
getnextb(off)
jnextb0 offmore_n2b
subl $ 3,off; jc len_n2b # use previous offset
shll $ 8,off; lodsb # off is %eax, so 'lodsb' is "off |= *src++;"
xorl $~0,off; jz eof_n2b
movslq off,dispq # XXX: 2GB; (note propagation of negative sign!)
// for 4GB, replace the 'movslq' with:
// pushq $~0 # 64 bits all '1'
// movl off,(%rsp) # replace lo-order 32 bits
// popq dispq
len_n2b:
lea 1(lenq),off # [len= 0] off= 1
getnextb(len); getnextb(len) # two bits; cc set on result
jnz gotlen_n2b # raw 1,2,3 ==> 2,3,4
movl off,len # len= 1, the msb
addl $3-1,off # raw 2.. ==> 5..
lenmore_n2b:
getnextb(len)
jnextb0 lenmore_n2b
gotlen_n2b:
cmpl $-0xd00,displ # XXX: 2GB; for 4GB: use 'cmpq'
adcl off,len # len += off + (disp < -0xd00)
push %rsi // MATCH_06
lea (%rdi,dispq),%rsi
rep; movsb
pop %rsi // MATCH_06
jmp top_n2b
eof_n2b:
pop old_sp // MATCH_10
pop %rcx // MATCH_11 &input_eof
cmp %rcx,%rsi; je 0f; hlt; 0: // test for ending in correct place
//FIXME: check dst, too
// Write de-compressed 'fold' to file
mov F_PMASK(old_sp),%rax; mov %rax,(%rsp) // propagate PAGE_MASK
mov F_LENU(old_sp),%arg3 // LENU
push %rsp; pop %arg2 // buffer
mov %r12,%arg1 // mfd
push $__NR_write; pop %rax; call sys_check
// de-alloca()
push old_sp; pop %rsp
// Map unfolded code the SELinux way
sub %arg6l,%arg6l // 0 offset
mov %r12,%arg5 // mfd
push $MAP_SHARED; pop %sys4
push %arg3; pop %arg2 // LENU
push $PROT_READ|PROT_EXEC; pop %arg3 // FIXME: add PROT_WRITE for DEBUG only
subl %edi,%edi // (%arg1)dst = 0; // kernel chooses addr
push $__NR_mmap; pop %rax; call sys_check
push %rax // MATCH_12
mov %rax,F_ADRU(old_sp)
push %arg5; pop %arg1 // mfd
push $__NR_close; pop %rax; syscall
// Use the copy.
pop %rax // MATCH_12 ADRU
add $D_FOLD,%rax // beyond .data
jmp *%rax // goto unfolded stub
zfind:
mov (%rdi),%rax; add $NBPW,%rdi
test %rax,%rax; jne zfind
ret
sys_check:
push %rax // save __NR_ for debug
syscall
pop %rcx // recover __NR_ for debug
cmp $-1<<12,%rax; jb 0f; hlt; 0:
ret
here: // OUT: %rdi= (2+ retaddrj) without disturbing shadow stack
mov (%rsp),%rdi
scasw // over jmp.s
ret
getbit:
addl bits,bits; jz refill // Carry= next bit
@ -155,133 +283,15 @@ getbit:
refill:
movl (%rsi),bits; subq $-4,%rsi // next 32 bits; set Carry
adcl bits,bits // LSB= 1 (CarryIn); CarryOut= next bit
movb (%rsi),%dl // speculate: literal, or bottom 8 bits of offset
rep; ret
copy: // In: len, %rdi, dispq; Out: 0==len, %rdi, dispq; trashes %rax, %rdx
leaq (%rdi,dispq),%rax; cmpl $5,len // <=3 is forced
movb (%rax),%dl; jbe copy1 // <=5 for better branch predict
cmpq $-4,dispq; ja copy1 // 4-byte chunks would overlap
subl $4,len // adjust for termination cases
copy4:
movl (%rax),%edx; addq $4, %rax; subl $4,len
movl %edx,(%rdi); leaq 4(%rdi),%rdi; jnc copy4
addl $4,len; movb (%rax),%dl; jz copy0
copy1:
incq %rax; movb %dl,(%rdi); subl $1,len
movb (%rax),%dl
leaq 1(%rdi),%rdi; jnz copy1
copy0:
rep; ret
setup:
cld
pop %r11 // addq $ getbit - ra_setup,%r11 # &getbit
section NRV2E
#include "arch/amd64/nrv2e_d.S"
section NRV2D
#include "arch/amd64/nrv2d_d.S"
section NRV2B
#include "arch/amd64/nrv2b_d.S"
#include "arch/amd64/lzma_d.S"
section NRV_TAIL
// empty
section ELFMAINY
eof:
pop %rcx // &input_eof
movq %rsi,%rax; subq %rcx,%rax // src -= eof; // return 0: good; else: bad
pop %rdx; subq %rdx,%rdi // dst -= original dst
pop %rcx; movl %edi,(%rcx) // actual length used at dst XXX: 4GB
pop %rbx; pop %rbp
ret
/* These from /usr/include/asm-x86_64/unistd.h */
__NR_exit= 60
__NR_mmap= 9
__NR_mprotect= 10
__NR_open= 2
__NR_write= 1
msg_SELinux:
push $ L71 - L70; pop %arg3 // length
call L72
L70:
.asciz "PROT_EXEC|PROT_WRITE failed.\n"
L71:
L72:
pop %arg2 // message text
L75:
push $FD_stderr; pop %arg1
push $ __NR_write; pop %rax
syscall
die:
push $127; pop %arg1
push $ __NR_exit; pop %rax
syscall
// IDENTSTR goes here
section ELFMAINZ
// Decompress the rest of this loader, and jump to it.
unfold: // IN: rbp= &f_exp; rsp/ &O_BINFO,%entry
pop %rsi // &(O_BINFO | is_ptinterp | unmap_all_pages)
lodsl; and $~(is_ptinterp|unmap_all_pages),%eax; movl %eax,%r14d // O_BINFO
push %rsi; pop %rbx // &b_info of folded decompressor
movl (%rsi),%edx // .sz_unc
lea sz_pack2 - f_exp(%rbp),%rcx // &sz_pack2
movl (%rcx),%r15d // sz_pack2: length before stub
subq %r15,%rcx // elfaddr= &Elf64_Ehdr of this stub
subl %r14d,%r15d // LENX= sz_pack2 - O_BINFO
addq %rcx,%r14 // ADRX= elfaddr + O_BINFO
push %rdx // LENU
push %rax // %ADRU
push $-1 // space for %fd
push %rcx // elfaddr
// Reserve space for unfolded stub.
subq %arg6,%arg6 // 0 offset
orl $-1,%arg5l // fd
push $MAP_PRIVATE|MAP_ANONYMOUS; pop %sys4
push %rdx; pop %arg2 // len
push $PROT_READ|PROT_WRITE; pop %arg3
subl %arg1l,%arg1l // 0; kernel chooses addr
push $__NR_mmap; pop %rax; syscall
movq %rax,2*8(%rsp) // ADRU
// Unfold
push %rax; pop %arg3 // dst= new unfold
push %rbx; pop %rsi
lodsl; push %rax; movq %rsp,%arg4 // P_13 .sz_unc; &dstlen
movq %arg3,%r13 // execute here
lodsl; push %rax // P_14 tmp= .sz_cpr
lodsl; xchg %eax,%arg5l // .b_method
movq %rsi,%arg1 // src
pop %arg2 // P_14 srclen
call *%rbp // f_exp
pop %rcx // P_13 toss .sz_unc
// PROT_EXEC
movq 3*8(%rsp),%arg2 // LENU
movq 2*8(%rsp),%arg1 // ADRU
push $PROT_READ|PROT_EXEC; pop %arg3
push $__NR_mprotect; pop %rax; syscall
// Use the copy.
// %r14= ADRX; %r15= LENX;
// rsp/ elfaddr,fd,ADRU,LENU,%entry
jmp *%r13
main:
pop %rbp // &f_exp
call unfold
.balign 4
o_binfo:
.long O_BINFO // offset of b_info for .text | is_ptinerp | unmap_all_pages
FOLD:
// { b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...}
/*__XTHEENDX__*/

View File

@ -32,9 +32,6 @@ NBPW= 8
#include "arch/amd64/regs.h"
PATH_MAX= 4096 // /usr/include/linux/limits.h
PAGE_SHIFT= 12 // /usr/include/sys/user.h
PAGE_SIZE= 1 << PAGE_SHIFT
PAGE_MASK= ~0 << PAGE_SHIFT
sz_b_info= 12
sz_unc= 0
@ -62,61 +59,66 @@ __NR_mmap= 9
__NR_mprotect= 10
__NR_munmap= 11
__NR_brk= 12
__NR_memfd_create= 0x13f // 319
__NR_ftruncate= 0x4d // 77
__NR_exit= 60
__NR_readlink= 89
// IN: [ADRX,+LENX): compressed data; [ADRU,+LENU): expanded fold (w/ upx_main)
// %rbx= 4+ &O_BINFO; %rbp= f_exp; %r14= ADRX; %r15= LENX;
// rsp/ elfaddr,%fd,ADRU,LENU,rdx,%entry, argc,argv,0,envp,0,auxv,0,strings
fold_begin:
//// int3 // DEBUG only
call L90
.asciz "/proc/self/exe"; .byte 0 // 16 bytes in all
#include "arch/amd64/bxx.S"
L90:
pop %rdx // "/proc/self/eax"
push %r14 // ADRX
push %r15 // LENX
lea 16(%rdx),%rax; push %rax # &amdbxx: f_unf
F_FRAME= 7*NBPW
F_ENTR= 6*NBPW; F_UNMAPA= F_ENTR
F_RDX= 5*NBPW
F_LENU= 4*NBPW
F_ADRU= 3*NBPW
F_ELFA= 2*NBPW
F_LENX= 1*NBPW
F_ADRX= 0*NBPW
unmap_all_pages= (1<<1)
is_ptinterp= (1<<0)
push %rsp; pop %rsi
testb $unmap_all_pages,-4(%rbx); jnz 0f; sub $PATH_MAX,%rsp; 0:
push %rsp; pop %rdi
push $10; pop %rcx; rep movsq # f_unf,LENX,ADRX,elfaddr,%fd,ADRU,LENU,rdx,%entry,argc
xor %eax,%eax
.balign 4
PAGE_MASK: .quad -1<<12 // default
// IN: [ADRX,+LENX): compressed data; [ADRU,+LENU): expanded fold (w/ upx_main)
// %rsp= %rbp= &F_ADRX; %r13= O_BINFO | is_ptinterp | unmap_all_pages
// no 'section', thus '.text'; also loaded first in amd64-linux.elf-fold.bin.
// Code from amd64-linux.elf-main.c is also .text, and is next.
fold_begin:
//// int3 # DEBUG
mov %r13,F_UNMAPA(%rbp)
mov %r13,%rax; and $is_ptinterp,%eax; or %eax,F_ELFA(%rbp)
mov %rsp,%rsi
testb $unmap_all_pages,F_UNMAPA(%rbp); jnz 0f; sub $PATH_MAX,%rsp; 0:
mov %rsp,%rdi
push $8; pop %rcx; rep movsq # ADRX,LDRX,ELFA,ADRU,LENU,rdx,%entry,argc
0:
cmpq %rax,(%rsi); movsq; jne 0b # move past argv
cmpq $0,(%rsi); movsq; jne 0b # move past argv
movq %rdi,%r14 # remember &new_env[0]
testb $unmap_all_pages,-4(%rbx); jnz 0f; stosq; 0: # space for new_env[0]
testb $unmap_all_pages,F_UNMAPA(%rbp); jnz 0f; stosq; 0: # space for new_env[0]
0:
cmpq %rax,(%rsi); movsq; jne 0b # move past env
mov %rdi,%r12 # &new Elf64_auxv
push %rsi; pop %arg4 # &old_auxv in case no_env_pse
cmpq $0,(%rsi); movsq; jne 0b # move past env
mov %rdi,%r12 # &old Elf64_auxv
mov %rdi,%arg4 # &auxv in case no_pse_env
0:
cmpq %rax,(%rsi); movsq; movsq; jne 0b # move past auxv
cmpq $0,(%rsi); movsq; movsq; jne 0b # move past auxv
mov %rdi,%r15 # beyond auxv
mov %rsi,%r13 # beginning of strings
sub %r15,%r12 # -length of auxv
sub %rdi,%r12 # -length of auxv
testb $unmap_all_pages,-4(%rbx); jz env_pse
mov %rdi,%r14; jmp no_env_pse # beyond auxv
testb $unmap_all_pages,F_UNMAPA(%rbp); jz env_pse
or $~0,%ebp; mov %rdi,%r14; jmp no_env_pse # no fd; beyond auxv
env_pse:
push %rdx; pop %arg1 # "/proc/self/exe"
push $O_RDONLY; pop %arg2
call open; mov %rax,4*NBPW(%rsp) # fd
push %rdi # buffer
lea proc_self_exe(%rip),%arg1; sub %arg2l,%arg2l # O_RDONLY
call open; mov %eax,%ebp # fd
pop %arg2 #buffer
movl $-1+ PATH_MAX,%arg3l # buflen
mov %r15,%arg2 # buffer (beyond auxv)
// %arg1 persists from open()
push $ __NR_readlink; pop %rax; syscall; testl %eax,%eax; jns 0f
// readlink() failed. Set the result equal to the argument.
push %arg1; pop %arg2 # result= "/proc/self/exe"
push %arg1; pop %arg2 # failure result= "/proc/self/exe"
push $15; pop %rax # 1+ strlen( )
0:
xchg %eax,%ecx # %ecx= byte count
@ -127,45 +129,50 @@ env_pse:
rep movsb # slide up
sub $3,%rdi; movl $('='<<24)|(' '<<16)|(' '<<8)|(' '<<0),(%rdi) # env var name
mov %rdi,(%r14) # new_env[0]
and $~0<<3,%rdi # align
and $-NBPW,%rdi # align
mov %r15,%rcx
sub %rsp,%rcx # byte count
mov %ecx,%eax
xor %edi,%eax
xor $NBPW,%eax
and $NBPW,%eax
sub %rax,%rdi # keep 16-byte alignment of %rsp
mov %rdi,%r14 # end of new auxv
sub $NBPW,%rdi # &last qword of new auxv
lea -NBPW(%r15),%rsi # &last qword of old auxv
// end of auxv must move by even number of NBPW
mov %edi,%eax
xor %esi,%eax
and $NBPW,%eax
sub %rax,%rdi
shr $3,%rcx; rep movsq
lea NBPW(%rdi),%rsp
cld
lea (%r14,%r12),%arg4 # &new Elf64_auxv
lea (%r14,%r12),%arg4 # &new Elf64_auxv %r12 dead
no_env_pse:
movl -4(%rbx),%eax; and $is_ptinterp,%eax; add %rax,%arg4
pop %arg6 # f_unf
pop %arg1 # ADRX with lo bits
pop %arg2 # LENX
pop %arg1 # ADRX
and $~(is_ptinterp | unmap_all_pages),%arg1
pop %rax # elfaddr
pop %arg5 # ELFA | is_ptinterp
mov %arg5l,%eax; and $1,%eax # is_ptinterp
or %rax,%arg4 # transfer is_ptinterp to &new_ELF64_auxv
sub %rax,%arg5 # and clear from ELFA
mov %arg5,%r13 # save ELFA
subq $ OVERHEAD,%rsp
movq %rsp,%arg3 # &ELf64_Ehdr temporary space
push %rax; mov %rax,%r13 # elfaddr 7th arg
movq %rbp,%arg5 # &decompress: f_expand
call upx_main # Out: %rax= entry
/* entry= upx_main(b_info *arg1, total_size arg2, Elf64_Ehdr *arg3,
Elf32_Auxv_t *arg4, f_decompr arg5, f_unf arg6,
Elf64_Addr elfaddr )
/* entry= upx_main(
b_info *arg1, {%rdi}
total_size arg2, {%rsi}
Elf64_Ehdr *arg3, {%rdx}
Elf32_Auxv_t *arg4, {%rcx}
Elf64_Addr elfaddr {%r8}
)
*/
// rsp/ elfaddr,{OVERHEAD},fd,ADRU,LENU,rdx,%entry, argc,argv,0,envp,0,auxv,0,strings
addq $1*NBPW+OVERHEAD,%rsp # also discard elfaddr
movq %rax,4*NBPW(%rsp) # entry
pop %rbx # fd
// rsp/ {OVERHEAD},ADRU,LENU,rdx,%entry, argc,argv,0,envp,0,auxv,0,strings
addq $OVERHEAD,%rsp # Elf64_Ehdr temporary space
mov %ebp,%ebx # fd
movq %rax,3*NBPW(%rsp) # entry
sz_Ehdr= 8*NBPW
e_type= 16
@ -185,7 +192,7 @@ p_memsz= 5*NBPW
mov %ebx,%arg5l # fd
push $MAP_PRIVATE; pop %arg4
push $PROT_READ; pop %arg3
mov $PAGE_SIZE,%arg2l
mov $1<<12,%arg2l
subl %arg1l,%arg1l # 0
call mmap
@ -197,43 +204,71 @@ no_pse_map:
push $__NR_munmap; pop %rax
jmp *-NBPW(%r14) # goto: syscall; pop %rdx; ret
get_page_mask: .globl get_page_mask
mov PAGE_MASK(%rip),%rax
ret
section SYSCALLS
my_bkpt: .globl my_bkpt
int3 // my_bkpt
ret
proc_self_exe:
.asciz "/proc/self/exe"
memfd_create: .globl memfd_create
mov $__NR_memfd_create,%eax; jmp sysgo2
Pmap: .globl Pmap // page-align the lo end
mov PAGE_MASK(%rip),%rax; not %rax // frag mask
and %arg1l,%eax // frag
sub %rax,%arg1
add %rax,%arg2
mmap: .globl mmap
movb $ __NR_mmap,%al
movq %arg4,%sys4
sysgo: # NOTE: kernel demands 4th arg in %sys4, NOT %arg4
movzbl %al,%eax
syscall
cmpq $ PAGE_MASK,%rax; jc no_fail
orq $~0,%rax # failure; IGNORE errno
no_fail:
sysgo2:
push %rax // save __NR_
syscall // %rax= -errno
pop %rcx // recover __NR_
cmp $-1<<12,%rax; jb sysOK
cmp $__NR_open,%ecx; je sysOK # ENOENT etc
int3 // %rax= errno; %rcx= __NR_
sysOK:
ret
Pprotect: .globl Pprotect
movl $~PAGE_MASK,%ecx // frag mask
and %edi,%ecx // frag
sub %rcx,%rdi
add %rcx,%rsi
mov PAGE_MASK(%rip),%eax; not %eax // frag mask
and %arg1l,%eax // frag
sub %rax,%rdi
add %rax,%rsi
jmp mprotect
Punmap: .globl Punmap // page-align the lo end
mov PAGE_MASK(%rip),%eax; not %eax // frag mask
and %arg1l,%eax // frag
sub %rax,%arg1
add %rax,%arg2
munmap: .globl munmap
movb $ __NR_munmap,%al; 5: jmp 5f
exit: .globl exit
movb $ __NR_exit,%al; 5: jmp 5f
brk: .globl brk
movb $ __NR_brk,%al; 5: jmp 5f
close: .globl close
movb $ __NR_close,%al; 5: jmp 5f
ftruncate: .globl ftruncate
movb $__NR_ftruncate,%al; 5: jmp 5f
open: .globl open
movb $ __NR_open,%al; 5: jmp 5f
munmap: .globl munmap
movb $ __NR_munmap,%al; 5: jmp 5f
mprotect: .globl mprotect
movb $ __NR_mprotect,%al; 5: jmp 5f
Pwrite: .globl Pwrite
write: .globl write
mov $__NR_write,%al; 5: jmp 5f
read: .globl read
movb $ __NR_read,%al; 5: jmp sysgo
my_bkpt: .globl my_bkpt
int3 // my_bkpt
ret
/* vim:set ts=8 sw=8 et: */

View File

@ -31,18 +31,8 @@
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
/*ENTRY(_start)*/
PHDRS
{
text PT_LOAD FILEHDR PHDRS FLAGS ( 5 ) ; /* r-x (no -w-) */
data PT_LOAD ; /* for setting brk(0) */
}
SECTIONS
{
. = 0x00100000 + SIZEOF_HEADERS + 12; /* 12==sizeof(l_info) */
.text : {
*(.text)
*(.data)
} : text
.data : {
} : data
}

View File

@ -0,0 +1,818 @@
/* amd64-linux.elf-main.c -- stub loader for Linux 64-bit ELF executable
This file is part of the UPX executable compressor.
Copyright (C) 1996-2024 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2024 Laszlo Molnar
Copyright (C) 2000-2024 John F. Reiser
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer Laszlo Molnar
<markus@oberhumer.com> <ezerotven+github@gmail.com>
John F. Reiser
<jreiser@users.sourceforge.net>
*/
#ifndef DEBUG //{
#define DEBUG 0
#endif //}
#include "include/linux.h"
extern void *memcpy(void *dst, void const *src, size_t n);
// Pprotect is mprotect but uses page-aligned address (Linux requirement)
extern unsigned Pprotect(void *, size_t, unsigned);
//extern void *Pmap(void *, size_t, unsigned, unsigned, int, size_t);
//extern int Punmap(void *, size_t);
extern size_t Pwrite(unsigned, void const *, size_t);
# define mmap_privanon(addr,len,prot,flgs) mmap((addr),(len),(prot), \
MAP_PRIVATE|MAP_ANONYMOUS|(flgs),-1,0)
extern void my_bkpt(void *, ...);
#if defined(__powerpc64__) //}{
#define addr_string(string) ({ \
char const *str; \
asm("bl 0f; .string \"" string "\"; .balign 4; 0: mflr %0" \
/*out*/ : "=r"(str) \
/* in*/ : \
/*und*/ : "lr"); \
str; \
})
#elif defined(__x86_64) //}{
#define addr_string(string) ({ \
char const *str; \
asm("call 0f; .asciz \"" string "\"; 0: pop %0" \
/*out*/ : "=r"(str) ); \
str; \
})
#elif defined(__aarch64__) //}{
#define addr_string(string) ({ \
char const *str; \
asm("bl 0f; .string \"" string "\"; .balign 4; 0: mov %0,x30" \
/*out*/ : "=r"(str) \
/* in*/ : \
/*und*/ : "x30"); \
str; \
})
#else //}{
#error;
#endif //}
#if !DEBUG //{
#define DPRINTF(fmt, args...) /*empty*/
#else //}{
// DPRINTF is defined as an expression using "({ ... })"
// so that DPRINTF can be invoked inside an expression,
// and then followed by a comma to ignore the return value.
// The only complication is that percent and backslash
// must be doubled in the format string, because the format
// string is processd twice: once at compile-time by 'asm'
// to produce the assembled value, and once at runtime to use it.
#if defined(__powerpc64__) //{
#define DPRINTF(fmt, args...) ({ \
char const *r_fmt; \
asm("bl 0f; .string \"" fmt "\"; .balign 4; 0: mflr %0" \
/*out*/ : "=r"(r_fmt) \
/* in*/ : \
/*und*/ : "lr"); \
dprintf(r_fmt, args); \
})
#elif defined(__x86_64) //}{
#define DPRINTF(fmt, args...) ({ \
char const *r_fmt; \
asm("call 0f; .asciz \"" fmt "\"; 0: pop %0" \
/*out*/ : "=r"(r_fmt) ); \
dprintf(r_fmt, args); \
})
#elif defined(__aarch64__) //}{
#define DPRINTF(fmt, args...) ({ \
char const *r_fmt; \
asm("bl 0f; .string \"" fmt "\"; .balign 4; 0: mov %0,x30" \
/*out*/ : "=r"(r_fmt) \
/* in*/ : \
/*und*/ : "x30"); \
dprintf(r_fmt, args); \
})
#endif //}
static int dprintf(char const *fmt, ...); // forward
#endif /*}*/
extern void my_bkpt(void *, ...);
/*************************************************************************
// configuration section
**************************************************************************/
// In order to make it much easier to move this code at runtime and execute
// it at an address different from it load address: there must be no
// static data, and no string constants.
#define ElfW(sym) Elf64_ ## sym
#include "MAX_ELF_HDR.c"
/*************************************************************************
// "file" util
**************************************************************************/
typedef struct {
size_t size; // must be first to match size[0] uncompressed size
char *buf;
} Extent;
static void
xread(Extent *x, char *buf, size_t count)
{
DPRINTF("xread x.size=%%x x.buf=%%p buf=%%p count=%%x\\n",
x->size, x->buf, buf, count);
char *p=x->buf, *q=buf;
size_t j;
if (x->size < count) {
exit(127);
}
for (j = count; 0!=j--; ++p, ++q) {
*q = *p;
}
x->buf += count;
x->size -= count;
DPRINTF("xread done count=%%x\\n", count);
}
/*************************************************************************
// util
**************************************************************************/
#if !DEBUG //{ save space
#define ERR_LAB error: exit(127);
#define err_exit(a) goto error
#else //}{ save debugging time
#define ERR_LAB /*empty*/
static void
err_exit(int a)
{
(void)a; // debugging convenience
DPRINTF("err_exit %%d\\n", a);
exit(127);
}
#endif //}
/*************************************************************************
// UPX & NRV stuff
**************************************************************************/
extern size_t get_page_mask(void); // variable page size AT_PAGESZ; see *-fold.S
int f_expand( // .globl in $(ARCH)-expand.S
nrv_byte const *binfo, nrv_byte *dst, size_t *dstlen);
static void
unpackExtent(
Extent *const xi, // input includes struct b_info
Extent *const xo // output
)
{
while (xo->size) {
DPRINTF("unpackExtent xi=(%%p %%p) xo=(%%p %%p)\\n",
xi->size, xi->buf, xo->size, xo->buf);
struct b_info h;
// Note: if h.sz_unc == h.sz_cpr then the block was not
// compressible and is stored in its uncompressed form.
// Read and check block sizes.
xread(xi, (char *)&h, sizeof(h));
DPRINTF("h.sz_unc=%%x h.sz_cpr=%%x h.b_method=%%x\\n",
h.sz_unc, h.sz_cpr, h.b_method);
if (h.sz_unc == 0) { // uncompressed size 0 -> EOF
if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic
err_exit(2);
if (xi->size != 0) // all bytes must be written
err_exit(3);
break;
}
if (h.sz_cpr <= 0) {
err_exit(4);
ERR_LAB
}
if (h.sz_cpr > h.sz_unc
|| h.sz_unc > xo->size ) {
err_exit(5);
}
// Now we have:
// assert(h.sz_cpr <= h.sz_unc);
// assert(h.sz_unc > 0 && h.sz_unc <= blocksize);
// assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize);
if (h.sz_cpr < h.sz_unc) { // Decompress block
size_t out_len = h.sz_unc; // EOF for lzma
int const j = f_expand((unsigned char *)xi->buf - sizeof(h),
(unsigned char *)xo->buf, &out_len);
if (j != 0 || out_len != (nrv_uint)h.sz_unc) {
DPRINTF(" j=%%x out_len=%%x &h=%%p\\n", j, out_len, &h);
err_exit(6);
}
xi->buf += h.sz_cpr;
xi->size -= h.sz_cpr;
}
else { // copy literal block
DPRINTF(" copy %%p %%p %%p\\n", xi->buf, xo->buf, h.sz_cpr);
xread(xi, xo->buf, h.sz_cpr);
}
xo->buf += h.sz_unc;
xo->size -= h.sz_unc;
}
}
#if defined(__x86_64__) //{
static void *
make_hatch_x86_64(
ElfW(Phdr) const *const phdr,
char *next_unc,
unsigned const frag_mask
)
{
char *hatch = next_unc;
unsigned const sz_code = 4;
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
if (sz_code <= (frag_mask & -(long)hatch)) {
((long *)hatch)[0] = 0xc35a050f; // syscall; pop %arg3{%rdx); ret
}
else { // Does not fit at hi end of .text, so must use a new page "permanently"
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
write(mfd, addr_string("\x0f\x05\x5a\xc3"), sz_code);
hatch = mmap(0, sz_code, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
close(mfd);
}
}
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#elif defined(__powerpc64__) //}{
static void *
make_hatch_ppc64(
ElfW(Phdr) const *const phdr,
char *next_unc,
unsigned const frag_mask
)
{
unsigned *hatch = (unsigned *)(~3& (3+ (long)next_unc));
unsigned const *code;
unsigned const sz_code = 4*4;
asm("bl 0f; \
sc; \
mr 12,31; \
li 4,0; \
blr; \
0: mflr %0 "
/*out*/ : "=r"(code)
/* in*/ :
/*und*/ : "lr");
DPRINTF("make_hatch %%p %%p %%x\\n",phdr,next_unc,frag_mask);
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
if (sz_code <= (frag_mask & -(long)hatch)) {
memcpy(hatch, code, sz_code);
}
else { // Does not fit at hi end of .text, so must use a new page "permanently"
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
write(mfd, code, sz_code);
hatch = mmap(0, sz_code, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
close(mfd);
}
}
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#elif defined(__aarch64__) //{
#define NBPI 4
#define NINSTR 3
static void *
make_hatch_arm64(
ElfW(Phdr) const *const phdr,
char *next_unc,
unsigned const frag_mask
)
{
unsigned *hatch = (unsigned *)(~3& (3+ (long)next_unc));
unsigned const *code;
unsigned const sz_code = 2*4;
asm ("bl 0f; \
svc #0; \
br x30; \
0: mov %0,x30"
/*out*/ : "=r"(code)
/* in*/ :
/*und*/ : );
DPRINTF("make_hatch %%p %%p %%x\\n",phdr,next_unc,frag_mask);
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
if (sz_code <= (frag_mask & -(long)hatch)) {
memcpy(hatch, code, sz_code);
}
else { // Does not fit at hi end of .text, so must use a new page "permanently"
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
write(mfd, code, sz_code);
hatch = mmap(0, sz_code, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
close(mfd);
}
}
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#undef NBPI
#undef NINSTR
#endif //}
#if defined(__powerpc64__) || defined(__aarch64__) //{ bzero
static void
upx_bzero(char *p, size_t len)
{
DPRINTF("bzero %%x %%x\\n", p, len);
if (len) do {
*p++= 0;
} while (--len);
}
#define bzero upx_bzero
#else //}{
#define bzero(a,b) __builtin_memset(a,0,b)
#endif //}
static void
auxv_up(ElfW(auxv_t) *av, unsigned const type, uint64_t const value)
{
if (!av || (1& (size_t)av)) { // none, or inhibited for PT_INTERP
return;
}
DPRINTF("\\nauxv_up %%d %%p\\n", type, value);
// Multiple slots can have 'type' which wastes space but is legal.
// rtld (ld-linux) uses the last one, so we must scan the whole table.
Elf64_auxv_t *ignore_slot = 0;
int found = 0;
for (;; ++av) {
DPRINTF(" %%d %%p\\n", av->a_type, av->a_un.a_val);
if (av->a_type == type) {
av->a_un.a_val = value;
++found;
}
else if (av->a_type == AT_IGNORE) {
ignore_slot = av;
}
if (av->a_type==AT_NULL) { // done scanning
if (found) {
return;
}
if (ignore_slot) {
ignore_slot->a_type = type;
ignore_slot->a_un.a_val = value;
return;
}
err_exit(20);
ERR_LAB
return;
}
}
}
// Segregate large local array, to avoid code bloat due to large displacements.
// Not 'static' to disaable inlining, to control sizeof stack frame in callers.
/*static*/ void
underlay(unsigned size, char *ptr, unsigned len) // len <= PAGE_SIZE
{
DPRINTF("underlay size=%%u ptr=%%p len=%%u\\n", size, ptr, len);
unsigned saved[4096/sizeof(unsigned)];
memcpy(saved, ptr, len);
mmap(ptr, size, PROT_WRITE|PROT_READ,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
memcpy(ptr, saved, len);
}
#if 0 //{
// Exchange the bits with values 4 (PF_R, PROT_EXEC) and 1 (PF_X, PROT_READ)
// Use table lookup into a PIC-string that pre-computes the result.
unsigned PF_TO_PROT(unsigned flags)
{
char const *table = addr_string("\x80\x04\x02\x06\x01\x05\x03\x07");
return 7& table[flags & (PF_R|PF_W|PF_X)];
}
#else //}{
// The PF_* and PROT_* bits are {1,2,4}; the conversion table fits in 32 bits.
#define REP8(x) \
((x)|((x)<<4)|((x)<<8)|((x)<<12)|((x)<<16)|((x)<<20)|((x)<<24)|((x)<<28))
#define EXP8(y) \
((1&(y)) ? 0xf0f0f0f0 : (2&(y)) ? 0xff00ff00 : (4&(y)) ? 0xffff0000 : 0)
#define PF_TO_PROT(pf) \
((PROT_READ|PROT_WRITE|PROT_EXEC) & ( \
( (REP8(PROT_EXEC ) & EXP8(PF_X)) \
|(REP8(PROT_READ ) & EXP8(PF_R)) \
|(REP8(PROT_WRITE) & EXP8(PF_W)) \
) >> ((pf & (PF_R|PF_W|PF_X))<<2) ))
#endif //}
// Find convex hull of PT_LOAD (the minimal interval which covers all PT_LOAD),
// and mmap that much, to be sure that a kernel using exec-shield-randomize
// won't place the first piece in a way that leaves no room for the rest.
static ElfW(Addr) // returns relocation constant
xfind_pages(unsigned mflags, ElfW(Phdr) const *phdr, int phnum,
ElfW(Addr) *const p_brk
, ElfW(Addr) const elfaddr
)
{
ElfW(Addr) lo= ~0, hi= 0, addr= 0;
mflags += MAP_PRIVATE | MAP_ANONYMOUS; // '+' can optimize better than '|'
DPRINTF("xfind_pages %%x %%p %%d %%p %%p\\n", mflags, phdr, phnum, elfaddr, p_brk);
for (; --phnum>=0; ++phdr) if (PT_LOAD==phdr->p_type) {
DPRINTF(" p_vaddr=%%p p_memsz=%%p\\n", phdr->p_vaddr, phdr->p_memsz);
if (phdr->p_vaddr < lo) {
lo = phdr->p_vaddr;
}
if (hi < (phdr->p_memsz + phdr->p_vaddr)) {
hi = phdr->p_memsz + phdr->p_vaddr;
}
}
size_t PMASK = get_page_mask();
lo -= ~PMASK & lo; // round down to page boundary
hi = PMASK & (hi - lo - PMASK -1); // page length
if (MAP_FIXED & mflags) {
addr = lo;
}
else if (0==lo) { // -pie ET_DYN
addr = elfaddr;
if (addr) {
mflags |= MAP_FIXED;
}
}
DPRINTF(" addr=%%p lo=%%p hi=%%p\\n", addr, lo, hi);
// PROT_WRITE allows testing of 64k pages on 4k Linux
addr = (ElfW(Addr))mmap((void *)addr, hi, (DEBUG ? PROT_WRITE : PROT_NONE), // FIXME XXX EVIL
mflags, -1, 0);
DPRINTF(" addr=%%p\\n", addr);
*p_brk = hi + addr; // the logical value of brk(0)
return (ElfW(Addr))(addr - lo);
}
static ElfW(Addr) // entry address
do_xmap(
ElfW(Ehdr) const *const ehdr,
Extent *const xi,
int const fdi,
ElfW(auxv_t) *const av,
ElfW(Addr) *const p_reloc
)
{
ElfW(Phdr) const *phdr = (ElfW(Phdr) const *)(void const *)(ehdr->e_phoff +
(char const *)ehdr);
ElfW(Addr) v_brk = 0;
ElfW(Addr) reloc = 0;
if (xi) { // compressed main program:
// C_BASE space reservation, C_TEXT compressed data and stub
ElfW(Addr) ehdr0 = *p_reloc; // the 'hi' copy!
ElfW(Phdr) *phdr0 = (ElfW(Phdr) *)(1+ (ElfW(Ehdr) *)ehdr0); // cheats .e_phoff
// Clear the 'lo' space reservation for use by PT_LOADs
ehdr0 -= phdr0[1].p_vaddr; // the 'lo' copy
if (ET_EXEC == ehdr->e_type) {
ehdr0 = phdr0[0].p_vaddr;
}
else {
reloc = ehdr0;
}
v_brk = phdr0->p_memsz + ehdr0;
munmap((void *)ehdr0, phdr0->p_memsz);
}
else { // PT_INTERP
DPRINTF("INTERP\\n", 0);
reloc = xfind_pages(
((ET_DYN!=ehdr->e_type) ? MAP_FIXED : 0), phdr, ehdr->e_phnum, &v_brk, *p_reloc
);
}
DPRINTF("do_xmap ehdr=%%p xi=%%p(%%x %%p) fdi=%%x\\n"
" av=%%p reloc=%%p p_reloc=%%p/%%p\\n",
ehdr, xi, (xi? xi->size: 0), (xi? xi->buf: 0), fdi,
av, reloc, p_reloc, *p_reloc);
size_t const page_mask = get_page_mask();
int j;
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
if (xi && PT_PHDR==phdr->p_type) {
auxv_up(av, AT_PHDR, phdr->p_vaddr + reloc);
} else
if (PT_LOAD==phdr->p_type && phdr->p_memsz != 0) {
unsigned const prot = PF_TO_PROT(phdr->p_flags);
DPRINTF("\\n\\nLOAD@%%p p_offset=%%p p_vaddr=%%p p_filesz=%%p"
" p_memsz=%%p p_flags=%%x prot=%%x\\n",
phdr, phdr->p_offset, phdr->p_vaddr, phdr->p_filesz,
phdr->p_memsz, phdr->p_flags, prot);
if (xi && !phdr->p_offset /*&& ET_EXEC==ehdr->e_type*/) { // 1st PT_LOAD
// ? Compressed PT_INTERP must not overwrite values from compressed a.out?
auxv_up(av, AT_PHDR, phdr->p_vaddr + reloc + ehdr->e_phoff);
auxv_up(av, AT_PHNUM, ehdr->e_phnum);
auxv_up(av, AT_PHENT, ehdr->e_phentsize); /* ancient kernels might omit! */
//auxv_up(av, AT_PAGESZ, PAGE_SIZE); /* ld-linux.so.2 does not need this */
}
Extent xo;
size_t mlen = xo.size = phdr->p_filesz;
char * addr = xo.buf = reloc + (char *)phdr->p_vaddr;
// xo.size, xo.buf are not changed except by unpackExtent()
char *const hi_addr = phdr->p_memsz + addr; // end of local .bss
char *addr2 = mlen + addr; // end of local .data
size_t frag = ~page_mask & (ElfW(Addr))addr;
mlen += frag;
addr -= frag;
#if defined(__powerpc64__) || defined(__aarch64__)
// Round up to hardware PAGE_SIZE; allows emulator with smaller.
// But (later) still need bzero when .p_filesz < .p_memsz .
mlen += -(mlen + (size_t)addr) &~ page_mask;
DPRINTF(" mlen=%%p\\n", mlen);
#endif
DPRINTF("mmap addr=%%p mlen=%%p offset=%%p frag=%%p prot=%%x\\n",
addr, mlen, phdr->p_offset - frag, frag, prot);
int mfd = 0;
if (xi && phdr->p_flags & PF_X) { // SELinux
// Cannot set PROT_EXEC except via mmap() into a region (Linux "vma")
// that has never had PROT_WRITE. So use a Linux-only "memory file"
// to hold the contents.
mfd = memfd_create(addr_string("upx"), 0); // the directory entry
ftruncate(mfd, mlen); // Allocate the pages in the file.
if (frag) {
write(mfd, addr, frag); // Save lo fragment of contents on first page.
}
if (addr != mmap(addr, mlen, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, mfd, 0)) {
err_exit(7);
}
}
else {
unsigned tprot = prot;
// Notice that first 4 args are same: mmap vs mmap_privanon
if (xi) {
tprot |= PROT_WRITE; // De-compression needs Write
tprot &= ~PROT_EXEC; // Avoid simultaneous Write and eXecute
if (addr != mmap_privanon(addr, mlen, tprot, MAP_FIXED|MAP_PRIVATE)) {
err_exit(11);
}
}
else if (addr != mmap(addr, mlen, tprot, MAP_FIXED|MAP_PRIVATE,
fdi, phdr->p_offset - frag)) {
err_exit(8);
}
}
DPRINTF("addr= %%p\\n", addr);
if (xi) {
DPRINTF("before unpack xi=(%%p %%p xo=(%%p %%p)\\n", xi->size, xi->buf, xo.size, xo.buf);
unpackExtent(xi, &xo); // updates xi and xo
DPRINTF(" after unpack xi=(%%p %%p xo=(%%p %%p)\\n", xi->size, xi->buf, xo.size, xo.buf);
}
if (PROT_WRITE & prot) { // note: read-only .bss not supported here
// Clear to end-of-page (first part of .bss or &_end)
unsigned hi_frag = -(long)addr2 &~ page_mask;
bzero(addr2, hi_frag);
addr2 += hi_frag; // will be page aligned
}
if (xi && phdr->p_flags & PF_X) {
#if defined(__x86_64) //{
void *const hatch = make_hatch_x86_64(phdr, xo.buf, ~page_mask);
#elif defined(__powerpc64__) //}{
void *const hatch = make_hatch_ppc64(phdr, xo.buf, ~page_mask);
#elif defined(__aarch64__) //}{
void *const hatch = make_hatch_arm64(phdr, xo.buf, ~page_mask);
#endif //}
if (0!=hatch) {
// Always update AT_NULL, especially for compressed PT_INTERP.
// Clearing lo bit of av is for i386 only; else is superfluous.
auxv_up((ElfW(auxv_t) *)(~1 & (size_t)av), AT_NULL, (size_t)hatch);
}
// SELinux: Map the contents of mfd as per *phdr.
DPRINTF("hatch protect addr=%%p mlen=%%p\\n", addr, mlen);
munmap(addr, mlen); // toss the VMA that has PROT_WRITE
if (addr != mmap(addr, mlen, prot, MAP_FIXED|MAP_SHARED, mfd, 0)) {
err_exit(9);
}
close(mfd);
}
else if ((PROT_WRITE|PROT_READ) != prot
&& 0!=Pprotect(addr, mlen, prot)) {
err_exit(10);
ERR_LAB
}
if (addr2 < hi_addr) { // pages for .bss beyond last page for p_filesz
DPRINTF("zmap addr2=%%p len=%%p\\n", addr2, hi_addr - addr2);
if (addr2 != mmap_privanon(addr2, hi_addr - addr2, prot, MAP_FIXED)) {
err_exit(10);
}
}
}
if (xi && ET_DYN!=ehdr->e_type) {
// Needed only if compressed shell script invokes compressed shell.
// Besides, fold.S needs _Ehdr that is tossed
// do_brk((void *)v_brk);
}
if (p_reloc) {
*p_reloc = reloc;
}
return ehdr->e_entry + reloc;
}
/*************************************************************************
// upx_main - called by our entry code
//
// This function is optimized for size.
**************************************************************************/
void *
upx_main( // returns entry address
/*arg1*/ struct b_info const *const bi, // 1st block header
/*arg2*/ size_t const sz_compressed, // total length
/*arg3*/ ElfW(Ehdr) *const ehdr, // temp char[sz_ehdr] for decompressing
/*arg4*/ ElfW(auxv_t) *const av
#if defined(__x86_64) //{
/*arg5*/ , ElfW(Addr) elfaddr // In: &ElfW(Ehdr) for stub
#elif defined(__powerpc64__) //}{
/*arg5*/ , ElfW(Addr) *p_reloc // In: &ElfW(Ehdr) for stub; Out: 'slide' for PT_INTERP
#elif defined(__aarch64__) //}{
/*arg5*/ , ElfW(Addr) elfaddr
#endif //}
)
{
DPRINTF("upx_main b_info=%%p sz_compressed=%%p ehdr=%%p av=%%p\\n",
bi, sz_compressed, ehdr, av);
#if defined(__powerpc64__)
DPRINTF(" p_reloc=%%p\\n", p_reloc);
#endif
Extent xo, xi1, xi2;
xo.buf = (char *)ehdr;
xo.size = bi->sz_unc; // can require bi aligned(4)
xi2.buf = CONST_CAST(char *, bi); xi2.size = bi->sz_cpr + sizeof(*bi);
xi1.buf = CONST_CAST(char *, bi); xi1.size = sz_compressed;
// ehdr = Uncompress Ehdr and Phdrs
unpackExtent(&xi2, &xo); // never filtered?
#if defined(__x86_64) || defined(__aarch64__) //{
ElfW(Addr) *const p_reloc = &elfaddr;
#endif //}
ElfW(Addr) page_mask = get_page_mask(); (void)page_mask;
DPRINTF("upx_main1 .e_entry=%%p p_reloc=%%p *p_reloc=%%p page_mask=%%p\\n",
ehdr->e_entry, p_reloc, *p_reloc, page_mask);
ElfW(Phdr) *phdr = (ElfW(Phdr) *)(1+ ehdr);
// De-compress Ehdr again into actual position, then de-compress the rest.
ElfW(Addr) entry = do_xmap(ehdr, &xi1, 0, av, p_reloc);
DPRINTF("upx_main2 entry=%%p *p_reloc=%%p\\n", entry, *p_reloc);
auxv_up(av, AT_ENTRY , entry);
{ // Map PT_INTERP program interpreter
phdr = (ElfW(Phdr) *)(1+ ehdr);
unsigned j;
for (j=0; j < ehdr->e_phnum; ++phdr, ++j) if (PT_INTERP==phdr->p_type) {
char const *const iname = *p_reloc + (char const *)phdr->p_vaddr;
int const fdi = open(iname, O_RDONLY, 0);
if (0 > fdi) {
err_exit(18);
}
if (MAX_ELF_HDR_64!=read(fdi, (void *)ehdr, MAX_ELF_HDR_64)) {
ERR_LAB
err_exit(19);
}
// We expect PT_INTERP to be ET_DYN at 0.
// Thus do_xmap will set *p_reloc = slide.
*p_reloc = 0; // kernel picks where PT_INTERP goes
entry = do_xmap(ehdr, 0, fdi, 0, p_reloc);
DPRINTF("interp p_reloc=%%p reloc=%%p\\n", p_reloc, *p_reloc);
auxv_up(av, AT_BASE, *p_reloc); // musl
close(fdi);
}
}
return (void *)entry;
}
#if DEBUG //{
static int
unsimal(unsigned x, char *ptr, int n)
{
unsigned m = 10;
while (10 <= (x / m)) m *= 10;
while (10 <= x) {
unsigned d = x / m;
x -= m * d;
m /= 10;
ptr[n++] = '0' + d;
}
ptr[n++] = '0' + x;
return n;
}
static int
decimal(int x, char *ptr, int n)
{
if (x < 0) {
x = -x;
ptr[n++] = '-';
}
return unsimal(x, ptr, n);
}
static int
heximal(unsigned long x, char *ptr, int n)
{
unsigned j = -1+ 2*sizeof(unsigned long);
unsigned long m = 0xful << (4 * j);
for (; j; --j, m >>= 4) { // omit leading 0 digits
if (m & x) break;
}
for (; m; --j, m >>= 4) {
unsigned d = 0xf & (x >> (4 * j));
ptr[n++] = ((10<=d) ? ('a' - 10) : '0') + d;
}
return n;
}
#define va_arg __builtin_va_arg
#define va_end __builtin_va_end
#define va_list __builtin_va_list
#define va_start __builtin_va_start
static int
dprintf(char const *fmt, ...)
{
int n= 0;
char const *literal = 0; // NULL
char buf[24]; // ~0ull == 18446744073709551615 ==> 20 chars
va_list va; va_start(va, fmt);
for (;;) {
char c = *fmt++;
if (!c) { // end of fmt
if (literal) {
goto finish;
}
break; // goto done
}
if ('%'!=c) {
if (!literal) {
literal = fmt; // 1 beyond start of literal
}
continue;
}
// '%' == c
if (literal) {
finish:
n += write(2, -1+ literal, fmt - literal);
literal = 0; // NULL
if (!c) { // fmt already ended
break; // goto done
}
}
switch (c= *fmt++) { // deficiency: does not handle _long_
default: { // un-implemented conversion
n+= write(2, -1+ fmt, 1);
} break;
case 0: { // fmt ends with "%\0" ==> ignore
goto done;
} break;
case 'u': {
n+= write(2, buf, unsimal(va_arg(va, unsigned), buf, 0));
} break;
case 'd': {
n+= write(2, buf, decimal(va_arg(va, int), buf, 0));
} break;
case 'p': {
buf[0] = '0';
buf[1] = 'x';
n+= write(2, buf, heximal((unsigned long)va_arg(va, void *), buf, 2));
} break;
case 'x': {
buf[0] = '0';
buf[1] = 'x';
n+= write(2, buf, heximal(va_arg(va, int), buf, 2));
} break;
} // 'switch'
}
done:
va_end(va);
return n;
}
#endif //}
/* vim:set ts=4 sw=4 et: */

View File

@ -2,57 +2,18 @@ file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn Flags
0 ELFMAINX 012 0 0 040 2**0 CONTENTS
1 NRV_HEAD 066 0 0 052 2**0 CONTENTS
2 NRV2E 0ba 0 0 0b8 2**0 CONTENTS
3 NRV2D 0a1 0 0 0172 2**0 CONTENTS
4 NRV2B 093 0 0 0213 2**0 CONTENTS
5 LZMA_ELF00 064 0 0 02a6 2**0 CONTENTS
6 LZMA_DEC10 09f7 0 0 030a 2**0 CONTENTS
7 LZMA_DEC20 09f7 0 0 0d01 2**0 CONTENTS
8 LZMA_DEC30 018 0 0 016f8 2**0 CONTENTS
9 NRV_TAIL 0 0 0 01710 2**0 CONTENTS
10 ELFMAINY 04b 0 0 01710 2**0 CONTENTS
11 ELFMAINZ 077 0 0 0175b 2**0 CONTENTS
0 ELFMAINX 016a 0 0 040 2**0 CONTENTS
1 ELFMAINZ 04 0 0 01ac 2**2 CONTENTS
SYMBOL TABLE:
0000000000000000 l d NRV_HEAD 0 NRV_HEAD
0000000000000000 l d LZMA_DEC30 0 LZMA_DEC30
0000000000000000 l d ELFMAINY 0 ELFMAINY
0000000000000000 l d ELFMAINZ 0 ELFMAINZ
0000000000000000 l d ELFMAINX 0 ELFMAINX
0000000000000000 l d NRV2E 0 NRV2E
0000000000000000 l d NRV2D 0 NRV2D
0000000000000000 l d NRV2B 0 NRV2B
0000000000000000 l d LZMA_ELF00 0 LZMA_ELF00
0000000000000000 l d LZMA_DEC10 0 LZMA_DEC10
0000000000000000 l d LZMA_DEC20 0 LZMA_DEC20
0000000000000000 l d NRV_TAIL 0 NRV_TAIL
0000000000000000 g ELFMAINX 0 _start
0000000000000000 *UND* 0 O_BINFO
RELOCATION RECORDS FOR [ELFMAINX]:
OFFSET TYPE VALUE
0000000000000003 R_X86_64_PC32 ELFMAINZ+0x0000000000000069
RELOCATION RECORDS FOR [NRV2E]:
OFFSET TYPE VALUE
00000000000000af R_X86_64_PC32 NRV_HEAD+0x0000000000000021
000000000000005c R_X86_64_PC32 ELFMAINY+0xfffffffffffffffc
RELOCATION RECORDS FOR [NRV2D]:
OFFSET TYPE VALUE
0000000000000096 R_X86_64_PC32 NRV_HEAD+0x0000000000000021
000000000000005c R_X86_64_PC32 ELFMAINY+0xfffffffffffffffc
RELOCATION RECORDS FOR [NRV2B]:
OFFSET TYPE VALUE
000000000000008b R_X86_64_PC32 NRV_HEAD+0x0000000000000021
0000000000000053 R_X86_64_PC32 ELFMAINY+0xfffffffffffffffc
RELOCATION RECORDS FOR [LZMA_ELF00]:
OFFSET TYPE VALUE
0000000000000006 R_X86_64_PC32 LZMA_DEC30+0x0000000000000012
0000000000000056 R_X86_64_PC32 ELFMAINZ+0xfffffffffffffffc
RELOCATION RECORDS FOR [ELFMAINZ]:
OFFSET TYPE VALUE
0000000000000073 R_X86_64_32 O_BINFO
0000000000000000 R_X86_64_32 O_BINFO

113
src/stub/tmp/amd64-linux.elf-fold.map generated vendored
View File

@ -6,96 +6,73 @@ Name Origin Length Attributes
Linker script and memory map
0x00000000001000bc . = ((0x100000 + SIZEOF_HEADERS) + 0xc)
0x000000000010004c . = ((0x100000 + SIZEOF_HEADERS) + 0xc)
.text 0x00000000001000bc 0x904
*(.text)
.text 0x00000000001000bc 0x1f0 tmp/amd64-linux.elf-fold.o
0x000000000010029a munmap
0x0000000000100261 mmap
0x00000000001002a2 write
0x00000000001002a6 read
0x00000000001002aa my_bkpt
0x0000000000100278 Pprotect
0x000000000010028a exit
0x000000000010028e brk
0x0000000000100296 open
0x000000000010029e mprotect
0x0000000000100292 close
.text 0x00000000001002ac 0x713 tmp/amd64-linux.elf-main.o
0x0000000000100878 upx_main
*fill* 0x00000000001009bf 0x1 00
.text 0x00000000001009c0 0x0 tmp/amd64-expand.o
*(.data)
.data 0x00000000001009c0 0x0 tmp/amd64-linux.elf-fold.o
.data 0x00000000001009c0 0x0 tmp/amd64-linux.elf-main.o
.data 0x00000000001009c0 0x0 tmp/amd64-expand.o
0x00000000001009c0 . = ALIGN (0x1)
0x00000000001009c0 __start_EXP_HEAD = .
.text 0x0000000000000000 0x909
.text 0x0000000000000000 0x160 tmp/amd64-linux.elf-fold.o
0x0000000000000158 get_page_mask
.text 0x0000000000000160 0x0 tmp/amd64-expand.o
.text 0x0000000000000160 0x7a9 tmp/amd64-linux.elf-main2.o
0x00000000000002b5 underlay
0x00000000000007d4 upx_main
EXP_HEAD 0x00000000001009c0 0xe0
EXP_HEAD 0x00000000001009c0 0xe0 tmp/amd64-expand.o
0x00000000001009c0 f_expand
0x0000000000100aa0 __stop_EXP_HEAD = .
0x0000000000100aa0 . = ALIGN (0x1)
0x0000000000100aa0 __start_NRV2E = .
EXP_HEAD 0x0000000000000000 0xe0
EXP_HEAD 0x0000000000000000 0xe0 tmp/amd64-expand.o
0x0000000000000000 f_expand
NRV2E 0x0000000000100aa0 0xe5
NRV2E 0x0000000000100aa0 0xe5 tmp/amd64-expand.o
0x0000000000100b85 __stop_NRV2E = .
0x0000000000100b85 . = ALIGN (0x1)
0x0000000000100b85 __start_NRV2D = .
NRV2E 0x0000000000000000 0xe5
NRV2E 0x0000000000000000 0xe5 tmp/amd64-expand.o
NRV2D 0x0000000000100b85 0xd7
NRV2D 0x0000000000100b85 0xd7 tmp/amd64-expand.o
0x0000000000100c5c __stop_NRV2D = .
0x0000000000100c5c . = ALIGN (0x1)
0x0000000000100c5c __start_NRV2B = .
NRV2D 0x0000000000000000 0xd7
NRV2D 0x0000000000000000 0xd7 tmp/amd64-expand.o
NRV2B 0x0000000000100c5c 0xc1
NRV2B 0x0000000000100c5c 0xc1 tmp/amd64-expand.o
0x0000000000100d1d __stop_NRV2B = .
NRV2B 0x0000000000000000 0xc1
NRV2B 0x0000000000000000 0xc1 tmp/amd64-expand.o
.data
.data 0x0000000000000000 0x0
.data 0x0000000000000000 0x0 tmp/amd64-linux.elf-fold.o
.data 0x0000000000000000 0x0 tmp/amd64-expand.o
.data 0x0000000000000000 0x0 tmp/amd64-linux.elf-main2.o
.bss 0x0000000000100d20 0x0
.bss 0x0000000000100d20 0x0 tmp/amd64-linux.elf-fold.o
.bss 0x0000000000100d20 0x0 tmp/amd64-linux.elf-main.o
.bss 0x0000000000100d20 0x0 tmp/amd64-expand.o
.rela.dyn 0x0000000000100d20 0x0
.rela.text 0x0000000000000000 0x0 tmp/amd64-linux.elf-fold.o
.bss 0x0000000000000000 0x0
.bss 0x0000000000000000 0x0 tmp/amd64-linux.elf-fold.o
.bss 0x0000000000000000 0x0 tmp/amd64-expand.o
.bss 0x0000000000000000 0x0 tmp/amd64-linux.elf-main2.o
LOAD tmp/amd64-linux.elf-fold.o
LOAD tmp/amd64-linux.elf-main.o
LOAD tmp/amd64-expand.o
LOAD tmp/amd64-linux.elf-main2.o
OUTPUT(tmp/amd64-linux.elf-fold.bin elf64-x86-64)
0x0000000000000000 . = ALIGN (0x1)
0x0000000000000000 __start_LZMA_ELF00 = .
SYSCALLS 0x0000000000000000 0x8e
SYSCALLS 0x0000000000000000 0x8e tmp/amd64-linux.elf-fold.o
0x0000000000000018 Pmap
0x000000000000006a munmap
0x000000000000007a ftruncate
0x000000000000002a mmap
0x0000000000000086 write
0x0000000000000011 memfd_create
0x000000000000008a read
0x0000000000000000 my_bkpt
0x0000000000000045 Pprotect
0x0000000000000086 Pwrite
0x000000000000005a Punmap
0x000000000000006e exit
0x0000000000000072 brk
0x000000000000007e open
0x0000000000000082 mprotect
0x0000000000000076 close
LZMA_ELF00 0x0000000000000000 0x64
LZMA_ELF00 0x0000000000000000 0x64 tmp/amd64-expand.o
0x0000000000000064 __stop_LZMA_ELF00 = .
0x0000000000000064 . = ALIGN (0x1)
0x0000000000000064 __start_LZMA_DEC10 = .
LZMA_DEC10 0x0000000000000000 0x9f7
LZMA_DEC10 0x0000000000000000 0x9f7 tmp/amd64-expand.o
0x00000000000009f7 __stop_LZMA_DEC10 = .
0x00000000000009f7 . = ALIGN (0x1)
0x00000000000009f7 __start_LZMA_DEC20 = .
LZMA_DEC20 0x0000000000000000 0x9f7
LZMA_DEC20 0x0000000000000000 0x9f7 tmp/amd64-expand.o
0x00000000000009f7 __stop_LZMA_DEC20 = .
0x00000000000009f7 . = ALIGN (0x1)
0x00000000000009f7 __start_LZMA_DEC30 = .
LZMA_DEC30 0x0000000000000000 0x18
LZMA_DEC30 0x0000000000000000 0x18 tmp/amd64-expand.o
0x0000000000000018 __stop_LZMA_DEC30 = .
0x0000000000000018 . = ALIGN (0x1)
0x0000000000000018 __start_EXP_TAIL = .
EXP_TAIL 0x0000000000000000 0xc
EXP_TAIL 0x0000000000000000 0xc tmp/amd64-expand.o
0x000000000000000c __stop_EXP_TAIL = .