mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
refactor PackVmlinuxBase::pack()
This commit is contained in:
parent
961031efc1
commit
745de1abab
788
src/p_vmlinx.cpp
788
src/p_vmlinx.cpp
|
@ -194,6 +194,220 @@ bool PackVmlinuxBase<T>::canPack()
|
|||
return 0 < n_ptload;
|
||||
}
|
||||
|
||||
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
||||
{
|
||||
if (ft->id == 0) {
|
||||
linker->defineSymbol("filter_length", 0);
|
||||
return false;
|
||||
}
|
||||
assert(ft->calls > 0);
|
||||
|
||||
if (0x50==(0xF0 & ft->id)) {
|
||||
linker->defineSymbol("FID", ft->id);
|
||||
linker->defineSymbol("CTO", ft->cto);
|
||||
}
|
||||
else {
|
||||
linker->defineSymbol("filter_cto", ft->cto);
|
||||
linker->defineSymbol("filter_length",
|
||||
(ft->id & 0xf) % 3 == 0 ? ft->calls :
|
||||
ft->lastcall - ft->calls * 4);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PackVmlinuxBase<T>::pack(OutputFile *fo)
|
||||
{
|
||||
unsigned fo_off = 0;
|
||||
Ehdr ehdro;
|
||||
U32 tmp_u32;
|
||||
|
||||
// NULL
|
||||
// .text(PT_LOADs) .note(1st page) .note(rest)
|
||||
// .shstrtab .symtab .strtab
|
||||
Shdr shdro[1+3+3];
|
||||
memset(shdro, 0, sizeof(shdro));
|
||||
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForCompression(file_size);
|
||||
|
||||
// .e_ident, .e_machine, .e_version, .e_flags
|
||||
memcpy(&ehdro, &ehdri, sizeof(ehdro));
|
||||
ehdro.e_type = Ehdr::ET_REL;
|
||||
ehdro.e_entry = 0;
|
||||
ehdro.e_phoff = 0;
|
||||
ehdro.e_shoff = sizeof(ehdro);
|
||||
ehdro.e_phentsize = 0;
|
||||
ehdro.e_phnum = 0;
|
||||
ehdro.e_shnum = 1+3+3;
|
||||
ehdro.e_shstrndx = 4;
|
||||
fo->write(&ehdro, sizeof(ehdro)); fo_off+= sizeof(ehdro);
|
||||
fo->write(shdro, sizeof(shdro)); fo_off+= sizeof(shdro);
|
||||
|
||||
ph.u_len = sz_ptload;
|
||||
fi->seek(phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
checkAlreadyPacked(ibuf + ph.u_len - 1024, 1024);
|
||||
|
||||
// prepare filter
|
||||
ph.filter = 0;
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = 0; // we are independent of actual runtime address; see ckt32
|
||||
|
||||
upx_compress_config_t cconf; cconf.reset();
|
||||
// limit stack size needed for runtime decompression
|
||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||
compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
|
||||
unsigned const txt_c_len = ph.c_len;
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
|
||||
defineDecompressorSymbols();
|
||||
defineFilterSymbols(linker, &ft);
|
||||
if (0x40==(0xf0 & ft.id)) {
|
||||
linker->defineSymbol("filter_length", ph.u_len); // redefine
|
||||
}
|
||||
relocateLoader();
|
||||
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader, getLoader(), lsize);
|
||||
patchPackHeader(loader, lsize);
|
||||
|
||||
#define shstrtab local_shstrtab // avoid -Wshadow warning
|
||||
char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";
|
||||
char const *p = shstrtab;
|
||||
while (0!=*p++) ;
|
||||
shdro[1].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[1].sh_type = Shdr::SHT_PROGBITS;
|
||||
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
|
||||
shdro[1].sh_offset = fo_off;
|
||||
shdro[1].sh_size = txt_c_len + lsize; // plus more ...
|
||||
shdro[1].sh_addralign = 1; // default
|
||||
|
||||
fo_off += write_vmlinux_head(fo, &shdro[1]);
|
||||
fo->write(obuf, txt_c_len); fo_off += txt_c_len;
|
||||
unsigned const a = (shdro[1].sh_addralign -1) & -txt_c_len;
|
||||
if (0!=a) { // align
|
||||
fo_off += a;
|
||||
shdro[1].sh_size += a;
|
||||
fo->seek(a, SEEK_CUR);
|
||||
}
|
||||
fo->write(loader, lsize); fo_off += lsize;
|
||||
|
||||
#if 0
|
||||
printf("%-13s: compressed : %8u bytes\n", getName(), txt_c_len);
|
||||
printf("%-13s: decompressor : %8u bytes\n", getName(), lsize);
|
||||
#endif
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// .note with 1st page --------------------------------
|
||||
ph.u_len = phdri[0].p_offset;
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[2].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[2].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[2].sh_offset = fo_off;
|
||||
shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[2].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size;
|
||||
|
||||
// .note with rest --------------------------------
|
||||
ph.u_len = file_size - (sz_ptload + phdri[0].p_offset);
|
||||
fi->seek(sz_ptload + phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
|
||||
// Temporarily decrease ph.level by about (1+ log2(sz_rest / sz_ptload))
|
||||
// to avoid spending unreasonable effort compressing large symbol tables
|
||||
// that are discarded 99.9% of the time anyway.
|
||||
int const old_level = ph.level;
|
||||
for (unsigned v = ((ph.u_len>>3) + ph.u_len) / sz_ptload; 0 < v; v>>=1) {
|
||||
if (0== --ph.level) {
|
||||
ph.level = 1;
|
||||
}
|
||||
}
|
||||
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||
ph.level = old_level;
|
||||
|
||||
// while (0!=*p++) ; // name is the same
|
||||
shdro[3].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[3].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[3].sh_offset = fo_off;
|
||||
shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[3].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size;
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[4].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[4].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[4].sh_offset = fo_off;
|
||||
shdro[4].sh_size = sizeof(shstrtab); // already includes terminating '\0'
|
||||
shdro[4].sh_addralign = 1;
|
||||
fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size;
|
||||
|
||||
fo_off = ~3 & (3+ fo_off); fo->seek(fo_off, SEEK_SET);
|
||||
while (0!=*p++) ;
|
||||
shdro[5].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[5].sh_type = Shdr::SHT_SYMTAB;
|
||||
shdro[5].sh_offset = fo_off;
|
||||
shdro[5].sh_size = 5*sizeof(Sym);
|
||||
//shdro[5].sh_flags = Shdr::SHF_INFO_LINK;
|
||||
shdro[5].sh_link = 6; // to .strtab for symbols
|
||||
shdro[5].sh_info = 1+3; // number of non-global symbols [binutils/bfd/elf.c]
|
||||
shdro[5].sh_addralign = 4;
|
||||
shdro[5].sh_entsize = sizeof(Sym);
|
||||
|
||||
Sym sec_sym;
|
||||
|
||||
// Symbol 0; no references, but bfd demands it.
|
||||
memset(&sec_sym, 0, sizeof(sec_sym));
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
|
||||
// Each section before .shstrtab needs a symbol.
|
||||
sec_sym.st_info = sec_sym.make_st_info(Sym::STB_LOCAL, Sym::STT_SECTION);
|
||||
sec_sym.st_other = Sym::STV_DEFAULT;
|
||||
sec_sym.st_shndx = 1; // .text
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
sec_sym.st_shndx = 2; // .note
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
sec_sym.st_shndx = 3; // .note
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
|
||||
// the symbol we care about
|
||||
Sym unc_ker;
|
||||
unc_ker.st_name = 1; // 1 byte into strtab
|
||||
unc_ker.st_value = 0;
|
||||
unc_ker.st_size = txt_c_len;
|
||||
unc_ker.st_info = unc_ker.make_st_info(Sym::STB_GLOBAL, Sym::STT_FUNC);
|
||||
unc_ker.st_other = Sym::STV_DEFAULT;
|
||||
unc_ker.st_shndx = 1; // .text
|
||||
fo->write(&unc_ker, sizeof(unc_ker)); fo_off += sizeof(unc_ker);
|
||||
|
||||
// '\0' before and after the name we want
|
||||
char const strtab[] = "\0decompress_kernel";
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[6].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[6].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[6].sh_offset = fo_off;
|
||||
shdro[6].sh_size = sizeof(strtab); // includes both '\0'
|
||||
shdro[6].sh_addralign = 1;
|
||||
fo->write(strtab, sizeof(strtab)); fo_off += sizeof(strtab);
|
||||
|
||||
fo->seek(0, SEEK_SET);
|
||||
fo->write(&ehdro, sizeof(ehdro));
|
||||
fo->write(&shdro, sizeof(shdro));
|
||||
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
throwNotCompressible();
|
||||
#undef shstrtab
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int PackVmlinuxBase<T>::canUnpack()
|
||||
{
|
||||
|
@ -213,7 +427,7 @@ int PackVmlinuxBase<T>::canUnpack()
|
|||
return false;
|
||||
|
||||
if (ehdri.e_type != Ehdr::ET_REL
|
||||
|| ehdri.e_shoff != sizeof(ehdri) // Shdr not contiguous with Ehdr
|
||||
//i386 fails || ehdri.e_shoff != sizeof(ehdri) // Shdr not contiguous with Ehdr
|
||||
|| ehdri.e_shentsize!=sizeof(Shdr)
|
||||
|| ehdri.e_shnum < 4
|
||||
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Shdr) + ehdri.e_shoff)
|
||||
|
@ -437,27 +651,6 @@ void PackVmlinuxARM::buildLoader(const Filter *ft)
|
|||
}
|
||||
|
||||
|
||||
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
||||
{
|
||||
if (ft->id == 0) {
|
||||
linker->defineSymbol("filter_length", 0);
|
||||
return false;
|
||||
}
|
||||
assert(ft->calls > 0);
|
||||
|
||||
if (0x50==(0xF0 & ft->id)) {
|
||||
linker->defineSymbol("FID", ft->id);
|
||||
linker->defineSymbol("CTO", ft->cto);
|
||||
}
|
||||
else {
|
||||
linker->defineSymbol("filter_cto", ft->cto);
|
||||
linker->defineSymbol("filter_length",
|
||||
(ft->id & 0xf) % 3 == 0 ? ft->calls :
|
||||
ft->lastcall - ft->calls * 4);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/i386-linux.kernel.vmlinux-head.h"
|
||||
static const
|
||||
|
@ -465,376 +658,53 @@ static const
|
|||
static const
|
||||
#include "stub/arm-linux.kernel.vmlinux-head.h"
|
||||
|
||||
void PackVmlinuxI386::pack(OutputFile *fo)
|
||||
unsigned PackVmlinuxI386::write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
)
|
||||
{
|
||||
unsigned fo_off = 0;
|
||||
Ehdr ehdro;
|
||||
U32 tmp_u32; // for external representation
|
||||
|
||||
// NULL
|
||||
// .text(PT_LOADs) .note(1st page) .note(rest)
|
||||
// .shstrtab /* .symtab .strtab */
|
||||
Shdr shdro[1+3+1/*+2*/];
|
||||
memset(shdro, 0, sizeof(shdro));
|
||||
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForCompression(file_size);
|
||||
|
||||
// .e_ident, .e_machine, .e_version, .e_flags
|
||||
memcpy(&ehdro, &ehdri, sizeof(ehdro));
|
||||
ehdro.e_type = Ehdr::ET_REL;
|
||||
ehdro.e_entry = 0;
|
||||
ehdro.e_phoff = 0;
|
||||
ehdro.e_shoff = 0; // later
|
||||
ehdro.e_phentsize = 0;
|
||||
ehdro.e_phnum = 0;
|
||||
ehdro.e_shnum = 1+3+1/*+2*/;
|
||||
ehdro.e_shstrndx = 4;
|
||||
fo->write(&ehdro, sizeof(ehdro)); fo_off+= sizeof(ehdro);
|
||||
|
||||
ph.u_len = sz_ptload;
|
||||
fi->seek(phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
checkAlreadyPacked(ibuf + ph.u_len - 1024, 1024);
|
||||
|
||||
// prepare filter
|
||||
ph.filter = 0;
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = 0; // we are independent of actual runtime address; see ckt32
|
||||
|
||||
upx_compress_config_t cconf; cconf.reset();
|
||||
// limit stack size needed for runtime decompression
|
||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||
compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
|
||||
defineFilterSymbols(linker, &ft);
|
||||
if (0x40==(0xf0 & ft.id)) {
|
||||
linker->defineSymbol("filter_length", ph.u_len); // redefine
|
||||
}
|
||||
defineDecompressorSymbols();
|
||||
relocateLoader();
|
||||
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader, getLoader(), lsize);
|
||||
patchPackHeader(loader, lsize);
|
||||
|
||||
#define shstrtab local_shstrtab // avoid -Wshadow warning
|
||||
char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";
|
||||
char const *p = shstrtab;
|
||||
while (0!=*p++) ;
|
||||
shdro[1].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[1].sh_type = Shdr::SHT_PROGBITS;
|
||||
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
|
||||
shdro[1].sh_offset = fo_off;
|
||||
shdro[1].sh_size = sizeof(stub_i386_linux_kernel_vmlinux_head) + ph.c_len + lsize;
|
||||
shdro[1].sh_addralign = 1;
|
||||
|
||||
// ENTRY_POINT
|
||||
fo->write(&stub_i386_linux_kernel_vmlinux_head[0], sizeof(stub_i386_linux_kernel_vmlinux_head)-2*(1+ 4) +1);
|
||||
tmp_u32 = ehdri.e_entry; fo->write(&tmp_u32, 4);
|
||||
fo->write(&stub_i386_linux_kernel_vmlinux_head[0],
|
||||
sizeof(stub_i386_linux_kernel_vmlinux_head)-2*(1+ 4) +1);
|
||||
U32 tmp_u32 = ehdri.e_entry; fo->write(&tmp_u32, 4);
|
||||
|
||||
// COMPRESSED_LENGTH
|
||||
fo->write(&stub_i386_linux_kernel_vmlinux_head[sizeof(stub_i386_linux_kernel_vmlinux_head)-(1+ 4)], 1);
|
||||
fo->write(&stub_i386_linux_kernel_vmlinux_head[
|
||||
sizeof(stub_i386_linux_kernel_vmlinux_head)-(1+ 4)], 1);
|
||||
tmp_u32 = ph.c_len; fo->write(&tmp_u32, 4);
|
||||
|
||||
fo_off += sizeof(stub_i386_linux_kernel_vmlinux_head);
|
||||
stxt->sh_size += sizeof(stub_i386_linux_kernel_vmlinux_head);
|
||||
|
||||
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
||||
fo->write(loader, lsize); fo_off += lsize;
|
||||
|
||||
#if 0
|
||||
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
||||
printf("%-13s: decompressor : %8u bytes\n", getName(), lsize);
|
||||
#endif
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// .note with 1st page --------------------------------
|
||||
ph.u_len = phdri[0].p_offset;
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
compress(ibuf, ph.u_len, obuf);
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[2].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[2].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[2].sh_offset = fo_off;
|
||||
shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[2].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size;
|
||||
|
||||
// .note with rest --------------------------------
|
||||
ph.u_len = file_size - (sz_ptload + phdri[0].p_offset);
|
||||
fi->seek(sz_ptload + phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
|
||||
// Temporarily decrease ph.level by about (1+ log2(sz_rest / sz_ptload))
|
||||
// to avoid spending unreasonable effort compressing large symbol tables
|
||||
// that are discarded 99.9% of the time anyway.
|
||||
int const old_level = ph.level;
|
||||
for (unsigned v = ((ph.u_len>>3) + ph.u_len) / sz_ptload; 0 < v; v>>=1) {
|
||||
if (0== --ph.level) {
|
||||
ph.level = 1;
|
||||
}
|
||||
}
|
||||
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||
ph.level = old_level;
|
||||
|
||||
// while (0!=*p++) ; // name is the same
|
||||
shdro[3].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[3].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[3].sh_offset = fo_off;
|
||||
shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[3].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size;
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[4].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[4].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[4].sh_offset = fo_off;
|
||||
shdro[4].sh_size = sizeof(shstrtab); // already includes terminating '\0'
|
||||
shdro[4].sh_addralign = 1;
|
||||
fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size;
|
||||
|
||||
#if 0 /*{ no symbols! */
|
||||
while (0!=*p++) ;
|
||||
fo_off = ~3 & (3+ fo_off);
|
||||
shdro[5].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[5].sh_type = Shdr::SHT_SYMTAB;
|
||||
shdro[5].sh_offset = fo_off;
|
||||
shdro[5].sh_size = 16; // XXX ?
|
||||
shdro[5].sh_link = 6; // to .strtab for symbols
|
||||
shdro[5].sh_addralign = 4;
|
||||
shdro[5].sh_entsize = 16; // XXX Sym
|
||||
fo->seek(fo_off, SEEK_SET);
|
||||
fo->write("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); fo_off += 16;
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[6].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[6].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[6].sh_offset = fo_off;
|
||||
shdro[6].sh_size = 1; // XXX ?
|
||||
shdro[6].sh_addralign = 1;
|
||||
fo->write("", 1); fo_off += 1;
|
||||
#endif /*}*/
|
||||
|
||||
fo_off = ~3 & (3+ fo_off);
|
||||
fo->seek(fo_off, SEEK_SET);
|
||||
ehdro.e_shoff = fo_off;
|
||||
fo->write(shdro, sizeof(shdro));
|
||||
|
||||
fo->seek(0, SEEK_SET);
|
||||
fo->write(&ehdro, sizeof(ehdro));
|
||||
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
throwNotCompressible();
|
||||
#undef shstrtab
|
||||
return sizeof(stub_i386_linux_kernel_vmlinux_head);
|
||||
}
|
||||
|
||||
void PackVmlinuxARM::pack(OutputFile *fo)
|
||||
void PackVmlinuxARM::defineDecompressorSymbols()
|
||||
{
|
||||
unsigned fo_off = 0;
|
||||
Ehdr ehdro;
|
||||
U32 tmp_u32;
|
||||
|
||||
// NULL
|
||||
// .text(PT_LOADs) .note(1st page) .note(rest)
|
||||
// .shstrtab .symtab .strtab
|
||||
Shdr shdro[1+3+3];
|
||||
memset(shdro, 0, sizeof(shdro));
|
||||
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForCompression(file_size);
|
||||
|
||||
// .e_ident, .e_machine, .e_version, .e_flags
|
||||
memcpy(&ehdro, &ehdri, sizeof(ehdro));
|
||||
ehdro.e_type = Ehdr::ET_REL;
|
||||
ehdro.e_entry = 0;
|
||||
ehdro.e_phoff = 0;
|
||||
ehdro.e_shoff = sizeof(ehdro); // later
|
||||
ehdro.e_phentsize = 0;
|
||||
ehdro.e_phnum = 0;
|
||||
ehdro.e_shnum = 1+3+3;
|
||||
ehdro.e_shstrndx = 4;
|
||||
fo->write(&ehdro, sizeof(ehdro)); fo_off+= sizeof(ehdro);
|
||||
fo->write(shdro, sizeof(shdro)); fo_off+= sizeof(shdro);
|
||||
|
||||
ph.u_len = sz_ptload;
|
||||
fi->seek(phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
checkAlreadyPacked(ibuf + ph.u_len - 1024, 1024);
|
||||
|
||||
// prepare filter
|
||||
ph.filter = 0;
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = 0; // we are independent of actual runtime address; see ckt32
|
||||
|
||||
upx_compress_config_t cconf; cconf.reset();
|
||||
// limit stack size needed for runtime decompression
|
||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||
compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
|
||||
unsigned const txt_c_len = ph.c_len;
|
||||
unsigned const txt_u_len = ph.u_len;
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
|
||||
linker->defineSymbol( "COMPRESSED_LENGTH", txt_c_len);
|
||||
linker->defineSymbol("UNCOMPRESSED_LENGTH", txt_u_len);
|
||||
linker->defineSymbol( "COMPRESSED_LENGTH", ph.c_len);
|
||||
linker->defineSymbol("UNCOMPRESSED_LENGTH", ph.u_len);
|
||||
linker->defineSymbol("METHOD", ph.method);
|
||||
}
|
||||
|
||||
defineFilterSymbols(linker, &ft);
|
||||
if (0x40==(0xf0 & ft.id)) {
|
||||
linker->defineSymbol("filter_length", ph.u_len); // redefine
|
||||
}
|
||||
defineDecompressorSymbols();
|
||||
relocateLoader();
|
||||
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader, getLoader(), lsize);
|
||||
patchPackHeader(loader, lsize);
|
||||
|
||||
#define shstrtab local_shstrtab // avoid -Wshadow warning
|
||||
char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";
|
||||
char const *p = shstrtab;
|
||||
while (0!=*p++) ;
|
||||
shdro[1].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[1].sh_type = Shdr::SHT_PROGBITS;
|
||||
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
|
||||
shdro[1].sh_offset = fo_off;
|
||||
shdro[1].sh_size = sizeof(stub_arm_linux_kernel_vmlinux_head) +
|
||||
txt_c_len + (3& -txt_c_len) + lsize;
|
||||
shdro[1].sh_addralign = 1;
|
||||
|
||||
unsigned PackVmlinuxARM::write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
)
|
||||
{
|
||||
// First word from vmlinux-head.S
|
||||
fo->write(&stub_arm_linux_kernel_vmlinux_head[0], 4);
|
||||
|
||||
// Second word
|
||||
tmp_u32 = (0xff000000 & BeLePolicy::get32(&stub_arm_linux_kernel_vmlinux_head[4]))
|
||||
| (0x00ffffff & (-1+ ((3+ txt_c_len)>>2)));
|
||||
U32 tmp_u32;
|
||||
unsigned const t = (0xff000000 &
|
||||
BeLePolicy::get32(&stub_arm_linux_kernel_vmlinux_head[4]))
|
||||
| (0x00ffffff & (-1+ ((3+ ph.c_len)>>2)));
|
||||
tmp_u32 = t;
|
||||
fo->write(&tmp_u32, 4);
|
||||
|
||||
fo_off += sizeof(stub_arm_linux_kernel_vmlinux_head);
|
||||
stxt->sh_addralign = 4;
|
||||
stxt->sh_size += sizeof(stub_arm_linux_kernel_vmlinux_head);
|
||||
|
||||
fo->write(obuf, txt_c_len); fo_off += txt_c_len;
|
||||
tmp_u32 = 0; fo->write(&tmp_u32, 3& -txt_c_len); fo_off += 3& -txt_c_len;
|
||||
fo->write(loader, lsize); fo_off += lsize;
|
||||
|
||||
#if 0
|
||||
printf("%-13s: compressed : %8u bytes\n", getName(), txt_c_len);
|
||||
printf("%-13s: decompressor : %8u bytes\n", getName(), lsize);
|
||||
#endif
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// .note with 1st page --------------------------------
|
||||
ph.u_len = phdri[0].p_offset;
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
compress(ibuf, ph.u_len, obuf);
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[2].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[2].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[2].sh_offset = fo_off;
|
||||
shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[2].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size;
|
||||
|
||||
// .note with rest --------------------------------
|
||||
ph.u_len = file_size - (sz_ptload + phdri[0].p_offset);
|
||||
fi->seek(sz_ptload + phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
|
||||
// Temporarily decrease ph.level by about (1+ log2(sz_rest / sz_ptload))
|
||||
// to avoid spending unreasonable effort compressing large symbol tables
|
||||
// that are discarded 99.9% of the time anyway.
|
||||
int const old_level = ph.level;
|
||||
for (unsigned v = ((ph.u_len>>3) + ph.u_len) / sz_ptload; 0 < v; v>>=1) {
|
||||
if (0== --ph.level) {
|
||||
ph.level = 1;
|
||||
}
|
||||
}
|
||||
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||
ph.level = old_level;
|
||||
|
||||
// while (0!=*p++) ; // name is the same
|
||||
shdro[3].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[3].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[3].sh_offset = fo_off;
|
||||
shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[3].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size;
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[4].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[4].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[4].sh_offset = fo_off;
|
||||
shdro[4].sh_size = sizeof(shstrtab); // already includes terminating '\0'
|
||||
shdro[4].sh_addralign = 1;
|
||||
fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size;
|
||||
|
||||
fo_off = ~3 & (3+ fo_off); fo->seek(fo_off, SEEK_SET);
|
||||
while (0!=*p++) ;
|
||||
shdro[5].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[5].sh_type = Shdr::SHT_SYMTAB;
|
||||
shdro[5].sh_offset = fo_off;
|
||||
shdro[5].sh_size = 5*sizeof(Sym);
|
||||
//shdro[5].sh_flags = Shdr::SHF_INFO_LINK;
|
||||
shdro[5].sh_link = 6; // to .strtab for symbols
|
||||
shdro[5].sh_info = 1+3; // number of non-global symbols [binutils/bfd/elf.c]
|
||||
shdro[5].sh_addralign = 4;
|
||||
shdro[5].sh_entsize = sizeof(Sym);
|
||||
|
||||
Sym sec_sym;
|
||||
|
||||
// Symbol 0; no references, but bfd demands it.
|
||||
memset(&sec_sym, 0, sizeof(sec_sym));
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
|
||||
// Each section before .shstrtab needs a symbol.
|
||||
sec_sym.st_info = sec_sym.get_st_info(Sym::STB_LOCAL, Sym::STT_SECTION);
|
||||
sec_sym.st_other = Sym::STV_DEFAULT;
|
||||
sec_sym.st_shndx = 1; // .text
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
sec_sym.st_shndx = 2; // .note
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
sec_sym.st_shndx = 3; // .note
|
||||
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
|
||||
|
||||
// the symbol we care about
|
||||
Sym unc_ker;
|
||||
unc_ker.st_name = 1; // 1 byte into strtab
|
||||
unc_ker.st_value = 0;
|
||||
unc_ker.st_size = txt_c_len;
|
||||
unc_ker.st_info = unc_ker.get_st_info(Sym::STB_GLOBAL, Sym::STT_FUNC);
|
||||
unc_ker.st_other = Sym::STV_DEFAULT;
|
||||
unc_ker.st_shndx = 1; // .text
|
||||
fo->write(&unc_ker, sizeof(unc_ker)); fo_off += sizeof(unc_ker);
|
||||
|
||||
// '\0' before and after the name we want
|
||||
char const strtab[] = "\0decompress_kernel";
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[6].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[6].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[6].sh_offset = fo_off;
|
||||
shdro[6].sh_size = sizeof(strtab); // includes both '\0'
|
||||
shdro[6].sh_addralign = 1;
|
||||
fo->write(strtab, sizeof(strtab)); fo_off += sizeof(strtab);
|
||||
|
||||
fo->seek(0, SEEK_SET);
|
||||
fo->write(&ehdro, sizeof(ehdro));
|
||||
fo->write(&shdro, sizeof(shdro));
|
||||
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
throwNotCompressible();
|
||||
#undef shstrtab
|
||||
return sizeof(stub_arm_linux_kernel_vmlinux_head);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1136,172 +1006,26 @@ void PackVmlinuxAMD64::buildLoader(const Filter *ft)
|
|||
}
|
||||
|
||||
|
||||
void PackVmlinuxAMD64::pack(OutputFile *fo)
|
||||
unsigned PackVmlinuxAMD64::write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
)
|
||||
{
|
||||
unsigned fo_off = 0;
|
||||
Ehdr ehdro;
|
||||
U32 tmp_u32; // for external representation
|
||||
|
||||
// NULL
|
||||
// .text(PT_LOADs) .note(1st page) .note(rest)
|
||||
// .shstrtab /* .symtab .strtab */
|
||||
Shdr shdro[1+3+1/*+2*/];
|
||||
memset(shdro, 0, sizeof(shdro));
|
||||
char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";
|
||||
char const *p = shstrtab;
|
||||
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForCompression(file_size);
|
||||
|
||||
// .e_ident, .e_machine, .e_version, .e_flags
|
||||
memcpy(&ehdro, &ehdri, sizeof(ehdro));
|
||||
ehdro.e_type = Ehdr::ET_REL;
|
||||
ehdro.e_entry = 0;
|
||||
ehdro.e_phoff = 0;
|
||||
ehdro.e_shoff = 0; // later
|
||||
ehdro.e_phentsize = 0;
|
||||
ehdro.e_phnum = 0;
|
||||
ehdro.e_shnum = 1+3+1/*+2*/;
|
||||
ehdro.e_shstrndx = 4;
|
||||
fo->write(&ehdro, sizeof(ehdro)); fo_off+= sizeof(ehdro);
|
||||
|
||||
ph.u_len = sz_ptload;
|
||||
fi->seek(phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
checkAlreadyPacked(ibuf + ph.u_len - 1024, 1024);
|
||||
|
||||
// prepare filter
|
||||
ph.filter = 0;
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = 0; // we are independent of actual runtime address; see ckt32
|
||||
|
||||
upx_compress_config_t cconf; cconf.reset();
|
||||
// limit stack size needed for runtime decompression
|
||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||
compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
|
||||
defineFilterSymbols(linker, &ft);
|
||||
if (0x40==(0xf0 & ft.id)) {
|
||||
linker->defineSymbol("filter_length", ph.u_len); // redefine
|
||||
}
|
||||
defineDecompressorSymbols();
|
||||
relocateLoader();
|
||||
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader, getLoader(), lsize);
|
||||
patchPackHeader(loader, lsize);
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[1].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[1].sh_type = Shdr::SHT_PROGBITS;
|
||||
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
|
||||
shdro[1].sh_offset = fo_off;
|
||||
shdro[1].sh_size = sizeof(stub_amd64_linux_kernel_vmlinux_head) + ph.c_len + lsize;
|
||||
shdro[1].sh_addralign = 1;
|
||||
|
||||
// ENTRY_POINT
|
||||
fo->write(&stub_amd64_linux_kernel_vmlinux_head[0], sizeof(stub_amd64_linux_kernel_vmlinux_head)-2*(1+ 4) +1);
|
||||
tmp_u32 = ehdri.e_entry; fo->write(&tmp_u32, 4);
|
||||
fo->write(&stub_amd64_linux_kernel_vmlinux_head[0],
|
||||
sizeof(stub_amd64_linux_kernel_vmlinux_head)-2*(1+ 4) +1);
|
||||
unsigned const t = BeLePolicy::get32(&ehdri.e_entry);
|
||||
U32 tmp_u32; tmp_u32 = t;
|
||||
fo->write(&tmp_u32, 4);
|
||||
|
||||
// COMPRESSED_LENGTH
|
||||
fo->write(&stub_amd64_linux_kernel_vmlinux_head[sizeof(stub_amd64_linux_kernel_vmlinux_head)-(1+ 4)], 1);
|
||||
fo->write(&stub_amd64_linux_kernel_vmlinux_head[
|
||||
sizeof(stub_amd64_linux_kernel_vmlinux_head)-(1+ 4)], 1);
|
||||
tmp_u32 = ph.c_len; fo->write(&tmp_u32, 4);
|
||||
|
||||
fo_off += sizeof(stub_amd64_linux_kernel_vmlinux_head);
|
||||
stxt->sh_size += sizeof(stub_amd64_linux_kernel_vmlinux_head);
|
||||
|
||||
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
||||
fo->write(loader, lsize); fo_off += lsize;
|
||||
|
||||
#if 0
|
||||
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
||||
printf("%-13s: decompressor : %8u bytes\n", getName(), lsize);
|
||||
#endif
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// .note with 1st page --------------------------------
|
||||
ph.u_len = phdri[0].p_offset;
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[2].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[2].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[2].sh_offset = fo_off;
|
||||
shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[2].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size;
|
||||
|
||||
// .note with rest --------------------------------
|
||||
ph.u_len = file_size - (sz_ptload + phdri[0].p_offset);
|
||||
fi->seek(sz_ptload + phdri[0].p_offset, SEEK_SET);
|
||||
fi->readx(ibuf, ph.u_len);
|
||||
|
||||
// Temporarily decrease ph.level by about (1+ log2(sz_rest / sz_ptload))
|
||||
// to avoid spending unreasonable effort compressing large symbol tables
|
||||
// that are discarded 99.9% of the time anyway.
|
||||
int const old_level = ph.level;
|
||||
for (unsigned v = ((ph.u_len>>3) + ph.u_len) / sz_ptload; 0 < v; v>>=1) {
|
||||
if (0== --ph.level) {
|
||||
ph.level = 1;
|
||||
}
|
||||
}
|
||||
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||
ph.level = old_level;
|
||||
|
||||
// while (0!=*p++) ; // name is the same
|
||||
shdro[3].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[3].sh_type = Shdr::SHT_NOTE;
|
||||
shdro[3].sh_offset = fo_off;
|
||||
shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len;
|
||||
shdro[3].sh_addralign = 1;
|
||||
tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4);
|
||||
fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size;
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[4].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[4].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[4].sh_offset = fo_off;
|
||||
shdro[4].sh_size = sizeof(shstrtab); // already includes terminating '\0'
|
||||
shdro[4].sh_addralign = 1;
|
||||
fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size;
|
||||
|
||||
#if 0 /*{ no symbols! */
|
||||
while (0!=*p++) ;
|
||||
fo_off = ~3 & (3+ fo_off);
|
||||
shdro[5].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[5].sh_type = Shdr::SHT_SYMTAB;
|
||||
shdro[5].sh_offset = fo_off;
|
||||
shdro[5].sh_size = 16; // XXX ?
|
||||
shdro[5].sh_link = 6; // to .strtab for symbols
|
||||
shdro[5].sh_addralign = 4;
|
||||
shdro[5].sh_entsize = 16; // XXX Sym
|
||||
fo->seek(fo_off, SEEK_SET);
|
||||
fo->write("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); fo_off += 16;
|
||||
|
||||
while (0!=*p++) ;
|
||||
shdro[6].sh_name = ptr_diff(p, shstrtab);
|
||||
shdro[6].sh_type = Shdr::SHT_STRTAB;
|
||||
shdro[6].sh_offset = fo_off;
|
||||
shdro[6].sh_size = 1; // XXX ?
|
||||
shdro[6].sh_addralign = 1;
|
||||
fo->write("", 1); fo_off += 1;
|
||||
#endif /*}*/
|
||||
|
||||
fo_off = ~3 & (3+ fo_off);
|
||||
fo->seek(fo_off, SEEK_SET);
|
||||
ehdro.e_shoff = fo_off;
|
||||
fo->write(shdro, sizeof(shdro));
|
||||
|
||||
fo->seek(0, SEEK_SET);
|
||||
fo->write(&ehdro, sizeof(ehdro));
|
||||
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
throwNotCompressible();
|
||||
return sizeof(stub_amd64_linux_kernel_vmlinux_head);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -81,8 +81,13 @@ protected:
|
|||
virtual bool is_valid_e_entry(Addr) = 0;
|
||||
virtual bool has_valid_vmlinux_head() = 0;
|
||||
virtual bool canPack();
|
||||
virtual void pack(OutputFile *fo);
|
||||
virtual int canUnpack(); // bool, except -1: format known, but not packed
|
||||
virtual void unpack(OutputFile *fo);
|
||||
virtual unsigned write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
) = 0;
|
||||
static int __acc_cdecl_qsort compare_Phdr(void const *aa, void const *bb);
|
||||
};
|
||||
|
||||
|
@ -99,13 +104,15 @@ public:
|
|||
virtual const int *getCompressionMethods(int method, int level) const;
|
||||
virtual const int *getFilters() const;
|
||||
|
||||
virtual void pack(OutputFile *fo);
|
||||
|
||||
protected:
|
||||
virtual void buildLoader(const Filter *ft);
|
||||
virtual Linker* newLinker() const;
|
||||
virtual bool is_valid_e_entry(Addr);
|
||||
virtual bool has_valid_vmlinux_head();
|
||||
virtual unsigned write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
@ -121,13 +128,16 @@ public:
|
|||
virtual const int *getCompressionMethods(int method, int level) const;
|
||||
virtual const int *getFilters() const;
|
||||
|
||||
virtual void pack(OutputFile *fo);
|
||||
|
||||
protected:
|
||||
virtual void buildLoader(const Filter *ft);
|
||||
virtual Linker* newLinker() const;
|
||||
virtual bool is_valid_e_entry(Addr);
|
||||
virtual bool has_valid_vmlinux_head();
|
||||
virtual void defineDecompressorSymbols();
|
||||
virtual unsigned write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
@ -143,13 +153,15 @@ public:
|
|||
virtual const int *getCompressionMethods(int method, int level) const;
|
||||
virtual const int *getFilters() const;
|
||||
|
||||
virtual void pack(OutputFile *fo);
|
||||
|
||||
protected:
|
||||
virtual void buildLoader(const Filter *ft);
|
||||
virtual Linker* newLinker() const;
|
||||
virtual bool is_valid_e_entry(Addr);
|
||||
virtual bool has_valid_vmlinux_head();
|
||||
virtual unsigned write_vmlinux_head(
|
||||
OutputFile *const fo,
|
||||
Shdr *const stxt
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user