diff --git a/NEWS b/NEWS index 2303e2c5..4040a30a 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,7 @@ Changes in 1.94 beta (XX XXX 2006): * support for mach/ppc32 * support for linux elf/ppc32 * support for linux elf/amd64 - * win32/pe: hopefully working "load config" support for .exes + * win32/pe: hopefully working "load config" support Changes in 1.93 beta (07 Feb 2005): * vmlinuz/386: fixes to support more kernels diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index 922b994a..e127667c 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -1482,25 +1482,47 @@ void PackW32Pe::processResources(Resource *res) // Load Configuration handling **************************************************************************/ -void PackW32Pe::processLoadConf() +void PackW32Pe::processLoadConf(Interval *iv) // pass 1 { if (IDSIZE(PEDIR_LOADCONF) == 0) return; - const upx_byte * const loadconf = ibuf + IDADDR(PEDIR_LOADCONF); + const unsigned lcaddr = IDADDR(PEDIR_LOADCONF); + const upx_byte * const loadconf = ibuf + lcaddr; soloadconf = get_le32(loadconf); if (soloadconf == 0) return; if (soloadconf > 256) throwCantPack("size of Load Configuration directory unexpected"); - if (IDSIZE(PEDIR_RELOC)) - throwCantPack("LoadConf + relocations yet not supported"); + // if there were relocation entries referring to the load config table + // then we need them for the copy of the table too + unsigned pos,type; + Reloc rel(ibuf + IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC)); + while (rel.next(pos, type)) + if (pos >= lcaddr && pos < lcaddr + soloadconf) + { + iv->add(pos - lcaddr, type); + // printf("loadconf reloc detected: %x\n", pos); + } oloadconf = new upx_byte[soloadconf]; memcpy(oloadconf, loadconf, soloadconf); } +void PackW32Pe::processLoadConf(Reloc *rel, const Interval *iv, + unsigned newaddr) // pass2 +{ + // now we have the address of the new load config table + // so we can create the new relocation entries + for (unsigned ic = 0; ic < iv->ivnum; ic++) + { + rel->add(iv->ivarr[ic].start + newaddr, iv->ivarr[ic].len); + //printf("loadconf reloc added: %x %d\n", + // iv->ivarr[ic].start + newaddr, iv->ivarr[ic].len); + } +} + // unsigned PackW32Pe::virta2objnum(unsigned addr,pe_section_t *sect,unsigned objs) @@ -1751,12 +1773,14 @@ void PackW32Pe::pack(OutputFile *fo) Resource res; Interval tlsiv(ibuf); + Interval loadconfiv(ibuf); Export xport((char*)(unsigned char*)ibuf); const unsigned dllstrings = processImports(); processTls(&tlsiv); // call before processRelocs!! processResources(&res); processExports(&xport); + processLoadConf(&loadconfiv); processRelocs(); //OutputFile::dump("x1", ibuf, usize); @@ -1984,7 +2008,7 @@ void PackW32Pe::pack(OutputFile *fo) } ic += soexport; - processLoadConf(); + processLoadConf(&rel, &loadconfiv, ic); ODADDR(PEDIR_LOADCONF) = soloadconf ? ic : 0; ODSIZE(PEDIR_LOADCONF) = soloadconf; ic += soloadconf; diff --git a/src/p_w32pe.h b/src/p_w32pe.h index e05e3e64..ddb75484 100644 --- a/src/p_w32pe.h +++ b/src/p_w32pe.h @@ -119,7 +119,8 @@ protected: unsigned crelocs; // rva of preprocessed fixups int big_relocs; - void processLoadConf(); + void processLoadConf(PackW32Pe_Reloc *, const PackW32Pe_Interval *, unsigned); + void processLoadConf(PackW32Pe_Interval *); upx_byte *oloadconf; unsigned soloadconf;