WinPE with TLS: fix relocation bugs
--strip-relocs not needed after bugfixes, but keep safety check. Thanks to @ml1050. https://github.com/upx/upx/issues/880 modified: pefile.cpp
This commit is contained in:
parent
09d7d08e55
commit
3068d19492
@ -1487,23 +1487,29 @@ void PeFile::processTls2(Reloc *const rel, const Interval *const iv, unsigned ne
|
|||||||
|
|
||||||
unsigned ic;
|
unsigned ic;
|
||||||
// NEW: if TLS callbacks are used, relocate the VA of the callback chain, too - Stefan Widmann
|
// NEW: if TLS callbacks are used, relocate the VA of the callback chain, too - Stefan Widmann
|
||||||
for (ic = 0; ic < (use_tls_callbacks ? sizeof(LE32) * cb_size : (sizeof(LE32) - 1) * cb_size);
|
for (ic = 0; ic < (unsigned) (use_tls_callbacks ? 4 : 3); ic++)
|
||||||
ic += cb_size)
|
rel->add_reloc(newaddr + ic * cb_size, reloc_type);
|
||||||
rel->add_reloc(newaddr + ic, reloc_type);
|
|
||||||
|
|
||||||
SPAN_S_VAR(tls, const tlsp, mb_otls);
|
SPAN_S_VAR(tls, const tlsp, mb_otls);
|
||||||
// now the relocation entries in the tls data area
|
// now the relocation entries in the tls data area
|
||||||
for (ic = 0; ic < iv->ivnum; ic += sizeof(LE32)) {
|
for (ic = 0; ic < iv->ivnum; ic++) {
|
||||||
SPAN_S_VAR(byte, const pp,
|
SPAN_S_VAR(byte, const pp,
|
||||||
otls + (iv->ivarr[ic].start - (tlsp->datastart - imagebase) + sizeof(tls)));
|
otls + (iv->ivarr[ic].start - (tlsp->datastart - imagebase) + sizeof(tls)));
|
||||||
LEXX *const p = (LEXX *) raw_bytes(pp, sizeof(LEXX));
|
LEXX *const p = (LEXX *) raw_bytes(pp, sizeof(LEXX));
|
||||||
cb_value_t kc = *p;
|
cb_value_t kc = *p;
|
||||||
if (kc < tlsp->dataend && kc >= tlsp->datastart) {
|
if (kc < tlsp->dataend && kc >= tlsp->datastart) {
|
||||||
|
// add a relocation entry referring to an address inside of the original tls data area
|
||||||
|
// - as the new tls area is moved, the referred address have to be also adjusted
|
||||||
kc += newaddr + sizeof(tls) - tlsp->datastart;
|
kc += newaddr + sizeof(tls) - tlsp->datastart;
|
||||||
*p = kc + imagebase;
|
*p = kc + imagebase;
|
||||||
rel->add_reloc(kc, iv->ivarr[ic].len);
|
rel->add_reloc(kc, iv->ivarr[ic].len);
|
||||||
} else {
|
} else {
|
||||||
unsigned const a = kc - imagebase;
|
// add a relocation entry referring to an address outside of the original tls data area
|
||||||
|
// by adding the difference of the new tlsdatastart and the old tlsdatastart to
|
||||||
|
// the address of the original relocation record
|
||||||
|
unsigned const a =
|
||||||
|
iv->ivarr[ic].start + (newaddr + sizeof(tls)) - (tlsp->datastart - imagebase);
|
||||||
|
// Must not overwrite compressed data
|
||||||
if (a < newaddr && !opt->win32_pe.strip_relocs)
|
if (a < newaddr && !opt->win32_pe.strip_relocs)
|
||||||
throwCantPack("relocation too low (%#x < %#x); try --strip-relocs", a, newaddr);
|
throwCantPack("relocation too low (%#x < %#x); try --strip-relocs", a, newaddr);
|
||||||
rel->add_reloc(a, iv->ivarr[ic].len);
|
rel->add_reloc(a, iv->ivarr[ic].len);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user