Chain-Load: verify building blocks of lazy-init

This commit is contained in:
Fischlurch 2023-11-24 23:26:41 +01:00
parent b00f4501a3
commit c658512d7b
3 changed files with 190 additions and 57 deletions

View file

@ -117,7 +117,7 @@ namespace lib {
char* anchorAddr = reinterpret_cast<char*> (unConst(anchor));
char* adjusted = anchorAddr + offset;
void* rawTarget = reinterpret_cast<void*> (adjusted);
return static_cast<TAR*> (adjusted);
return static_cast<TAR*> (rawTarget);
}
@ -129,7 +129,7 @@ namespace lib {
* exploited as a trick to allow for automatic late initialisation
* in a situation, were a functor needs to capture references.
*/
const ptrdiff_t PAYLOAD_OFFSET =
const ptrdiff_t FUNCTOR_PAYLOAD_OFFSET =
[]{
size_t slot{42};
std::function<RawAddr(void)> probe = [slot]{ return RawAddr(&slot); };
@ -272,6 +272,14 @@ namespace lib {
}
template<class SIG>
void
installEmptyInitialiser()
{
pendingInit_.reset (new HeapStorage{emptyInitialiser<SIG>()});
}
private:
template<class SIG>
DelegateType<SIG>
emptyInitialiser()
@ -283,40 +291,6 @@ namespace lib {
return disabledFunctor;
});
}
template<class SIG>
void
installEmptyInitialiser()
{
pendingInit_.reset (new HeapStorage{emptyInitialiser<SIG>()});
}
private:
template<class SIG, class INI>
DelegateType<SIG>
buildInitialiserDelegate (std::function<SIG>& targetFunctor, INI&& initialiser)
{
using TargetFun = std::function<SIG>;
return DelegateType<SIG>{
[performInit = forward<INI> (initialiser)
,targetOffset = captureRawAddrOffset (this, &targetFunctor)]
(RawAddr location) -> TargetFun&
{// apply known offset backwards to find current location of the host object
TargetFun* target = relocate<TargetFun> (location, -PAYLOAD_OFFSET);
LazyInit* self = relocate<LazyInit> (target, -targetOffset);
REQUIRE (self);
performInit (self);
self->pendingInit_.reset();
return *target;
}};
}
template<class SIG>
DelegateType<SIG>*
getPointerToDelegate(HeapStorage& buffer)
{
return reinterpret_cast<DelegateType<SIG>*> (&buffer);
}
template<class SIG, class INI>
PendingInit
@ -329,6 +303,32 @@ namespace lib {
targetFunctor = TrojanFun<SIG>::generateTrap (getPointerToDelegate<SIG> (*storageHandle));
return storageHandle;
}
template<class SIG>
DelegateType<SIG>*
getPointerToDelegate(HeapStorage& buffer)
{
return reinterpret_cast<DelegateType<SIG>*> (&buffer);
}
template<class SIG, class INI>
DelegateType<SIG>
buildInitialiserDelegate (std::function<SIG>& targetFunctor, INI&& initialiser)
{
using TargetFun = std::function<SIG>;
return DelegateType<SIG>{
[performInit = forward<INI> (initialiser)
,targetOffset = captureRawAddrOffset (this, &targetFunctor)]
(RawAddr location) -> TargetFun&
{// apply known offset backwards to find current location of the host object
TargetFun* target = relocate<TargetFun> (location, -FUNCTOR_PAYLOAD_OFFSET);
LazyInit* self = relocate<LazyInit> (target, -targetOffset);
REQUIRE (self);
performInit (self);
self->pendingInit_.reset();
return *target;
}};
}
};

View file

@ -73,22 +73,11 @@ namespace test{
void
run (Arg)
{
simpleUse();
verify_trojanLambda();
verify_inlineStorage();
// verify_numerics();
// verify_adaptMapping();
// verify_dynamicChange();
}
/** @test demonstrate a basic usage scenario
*/
void
simpleUse()
{
verify_TargetRelocation();
verify_triggerMechanism();
verify_lazyInitialisation();
}
@ -203,6 +192,112 @@ namespace test{
/** @test verify navigating an object structure
* by applying known offsets consecutively
* from a starting point within an remote instance
* @remark in the real usage scenario, we know _only_ the offset
* and and attempt to find home without knowing the layout.
*/
void
verify_TargetRelocation()
{
struct Nested
{
int unrelated{rand()};
int anchor{rand()};
};
struct Demo
{
Nested nested;
virtual ~Demo(){ };
virtual RawAddr peek()
{
return &nested.anchor;
}
};
// find out generic offset...
const ptrdiff_t offNested = []{
Nested probe;
return captureRawAddrOffset(&probe, &probe.anchor);
}();
Demo here;
// find out actual offset in existing object
const ptrdiff_t offBase = captureRawAddrOffset(&here, &here.nested);
CHECK (offBase > 0);
CHECK (offNested > 0);
// create a copy far far away...
auto farAway = std::make_unique<Demo> (here);
// reconstruct base address from starting point
RawAddr startPoint = farAway->peek();
Nested* farNested = relocate<Nested>(startPoint, -offNested);
CHECK (here.nested.unrelated == farNested->unrelated);
Demo* farSelf = relocate<Demo> (farNested, -offBase);
CHECK (here.nested.anchor == farSelf->nested.anchor);
CHECK (isSameObject (*farSelf, *farAway));
}
/** @test demonstrate the trigger mechanism in isolation
*/
void
verify_triggerMechanism()
{
using Fun = std::function<float(int)>;
Fun theFun;
CHECK (not theFun);
int report{0};
auto delegate = [&report](RawAddr insideFun) -> Fun&
{
auto realFun = [&report](int num)
{
report += num;
return num + 23.55f;
};
Fun& target = *relocate<Fun>(insideFun, -FUNCTOR_PAYLOAD_OFFSET);
report = -42; // as proof that the init-delegate was invoked
target = realFun;
return target;
};
CHECK (not theFun);
// install the init-»trap«
theFun = TrojanFun<float(int)>::generateTrap (&delegate);
CHECK (theFun);
CHECK (0 == report);
// invoke function
int feed{1+rand()%100};
float res = theFun (feed);
// delegate *and* realFun were invoked
CHECK (feed == report + 42);
CHECK (res = feed -42 +23.55f);
// again...
report = 0;
feed = -1-rand()%20;
res = theFun (feed);
// this time the delegate was *not* invoked,
// only the installed realFun
CHECK (feed == report);
CHECK (res = feed + 23.55f);
}
/** @test demonstrate a basic usage scenario
*/
void
verify_lazyInitialisation()
{
}
};

View file

@ -97283,8 +97283,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="pencil"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700786308827" ID="ID_627670298" MODIFIED="1700792001666" TEXT="der Trojanische-Funktor">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700786308827" ID="ID_627670298" MODIFIED="1700865645701" TEXT="der Trojanische-Funktor">
<icon BUILTIN="button_ok"/>
<node COLOR="#5b280f" CREATED="1700786329960" ID="ID_579721558" MODIFIED="1700829943723" TEXT="bettet einen shared_ptr ein">
<linktarget COLOR="#e64156" DESTINATION="ID_579721558" ENDARROW="Default" ENDINCLINATION="581;-41;" ID="Arrow_ID_1803799256" SOURCE="ID_1318522029" STARTARROW="None" STARTINCLINATION="-98;-231;"/>
<icon BUILTIN="button_cancel"/>
@ -97304,11 +97304,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786402490" ID="ID_846455233" MODIFIED="1700786418812" TEXT="Trick-Mechanismus zur this-Ermittlung">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786427859" ID="ID_569731992" MODIFIED="1700795340778" TEXT="mu&#xdf; zu Beginn &#xbb;proben&#xab;">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1700786427859" ID="ID_569731992" MODIFIED="1700865640264" TEXT="mu&#xdf; zu Beginn &#xbb;proben&#xab;">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786446976" ID="ID_646471757" MODIFIED="1700795338010" TEXT="Zusatz-Problem: das &#x3bb; sieht nur seine capture">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1700786446976" ID="ID_646471757" MODIFIED="1700865636679" TEXT="Zusatz-Problem: das &#x3bb; sieht nur seine capture">
<icon BUILTIN="button_ok"/>
<node CREATED="1700786476589" ID="ID_1376774629" MODIFIED="1700786490117" TEXT="&#x27f6; also mehrstufig vorgehen"/>
<node CREATED="1700786494226" ID="ID_990128277" MODIFIED="1700786508492" TEXT="generisch das Verh&#xe4;ltnis zur std::function ermitteln"/>
<node CREATED="1700786514967" ID="ID_1504854205" MODIFIED="1700786531452" TEXT="ebenso das Verh&#xe4;ltnis von der std::function zu *this"/>
@ -97393,7 +97393,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1700846290266" ID="ID_1685278359" MODIFIED="1700846318281" TEXT="Also bleibt nur: LazyInit packt den eigentlichen Initialiser in einen opaque container"/>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700856150252" ID="ID_1283688015" MODIFIED="1700856166026" TEXT="Address-Relocation">
<node COLOR="#435e98" CREATED="1700856150252" ID="ID_1283688015" MODIFIED="1700865608154" TEXT="Address-Relocation">
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1700856167326" ID="ID_903304450" MODIFIED="1700856175977" TEXT="der Compiler weint und winselt">
<icon BUILTIN="broken-line"/>
@ -97412,6 +97412,44 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700856538050" ID="ID_30859769" MODIFIED="1700856555062" TEXT="aber die Layout-Annahme selber kann ich leider nicht pr&#xfc;fen">
<icon BUILTIN="clanbomber"/>
</node>
<node COLOR="#338800" CREATED="1700865572986" ID="ID_819138430" MODIFIED="1700865582889" TEXT="zumindest im Test nachgestellt und funktioniert">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700865668069" ID="ID_96300659" MODIFIED="1700865853252" TEXT="Speicherverwaltung">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1700865679180" ID="ID_3672857" MODIFIED="1700865823343">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
OpaqueHolder<i>&#160;mi&#223;braucht</i>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
<node CREATED="1700865718074" ID="ID_46417679" MODIFIED="1700865732256" TEXT="er setzt eigentlich gemeinsame Basisklasse vorraus"/>
<node CREATED="1700865733257" ID="ID_19147628" MODIFIED="1700865768147" TEXT="InPlaceAnyHolder w&#xfc;rde den Fall unterst&#xfc;tzen, ist aber zu schwergewichtig (VTable)"/>
<node CREATED="1700865775966" ID="ID_1852703821" MODIFIED="1700865806222" TEXT="ist hier grade noch so machbar, da wir das Objekt nach Erstellung nur noch verwalten"/>
</node>
<node COLOR="#338800" CREATED="1700865829132" ID="ID_1420005046" MODIFIED="1700865850429" TEXT="shared_ptr nach Triggern der Initialisierung reset()">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1700865861639" ID="ID_409549839" MODIFIED="1700865919942" TEXT="gegebenes Init-&#x3bb; adaptieren">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1700865886375" ID="ID_594517704" MODIFIED="1700865897328" TEXT="self-Offset capture">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1700865898011" ID="ID_831512370" MODIFIED="1700865904118" TEXT="self-Offset restore">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1700865906981" ID="ID_1800834277" MODIFIED="1700865917596" TEXT="am Ende Referenz auf target-Functor liefern">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node COLOR="#c1019e" CREATED="1700856585458" ID="ID_373199802" MODIFIED="1700856611800" TEXT="ich f&#xfc;hl mich schei&#xdf;e">