Multi-architecture binaries

Pragma ericanderton at yahoo.removeme.com
Wed May 2 09:06:25 PDT 2007


Don Clugston wrote:
> Jascha Wetzel wrote:
>> here is a much simpler version that works with templates. what is boils
>> down to is choosing one template instance at startup that will replace a
>> function pointer.
>>
>> now the only compiler support required would be a pragma or similar to
>> select the target architecture.
> 
> A pragma would only be required as a size optimisation. Probably not 
> worth worrying about (We have enough version information already).
> 
>> this could also be used to manage multiple versions of BLADE code.
> 
> It's a nice idea, but I don't know how it could generate the class to 
> put the 'this()' function into (we don't want a memory alloc every time 
> we enter that function!)
> 
> Interestingly DDL could be fantastic for this. At startup, walk through 
> the symbol fixup table, and look for any import symbols marked 
> __cpu_fixup_XXX.
> When you find them, look for an export symbol called __cpu_SSE2_XXX, and 
> patch them into everything in the the fixup list. That way, you even get 
> a direct function call, instead of an indirect one.

I was thinking about this.  What would be nice is if D had reflection annotations/attributes to flag methods and 
functions, rather than kluding more information into the symbol name.

pragma(attr,CPUOptionFixup(CPU.SSE2,&myFunction))
void myFunction_SSE2(){ /* do something with SSE2 */ }

void myFunction(){ /* use vanilla code here */ }

During, or after link-time, you just walk the reflection metadata and patch things up as appropriate.

Now DDL already has a metadata capability via .ddl wrapper support - your imagination is the limit on how that is done 
post-build (a D front-end comes to mind).  Once I get this next revision of DDL out, it should be possible to publish 
DDL metadata directly from a module via a static hashmap, instead of relying on a post-build process.

Either way, it's just a matter of walking that metadata as it's exposed from each DynamicModule and DynamicLibrary, and 
patching the symbol tables during runtime linking.

> 
> I wonder if it's possible to pop ESP off the stack, and write back into 
> the code that called you, without the operating system triggering a 
> security alert -- in that case, the function you call could be a little 
> thunk, something like:
> 
> asm {
>   naked;
>   mov eax, CPU_TYPE;
>   mov eax, FUNCPOINTERS[eax];
>   mov ecx, [esp-4]; // get the return address
>   mov [ecx-4], eax; // patch the call address, so this thunk never gets 
> called again.
>   jmp [eax];
> }
> 
> But I think a modern OS would go nuts if you try this?
> (It's been a long time since I wrote self modifying code).

If I'm not mistaken, this should be doable thanks to D adopting a *very* flat memory model (at least on win32).  All the 
segment registers have the same base address in memory.  So just as long as you read/write against ES/DS/FS/GS/SS and 
read/call against CS, you should be good to go.

IIRC, Windows does provide some stronger code-segment write protection (I forget what it was actually called), but it 
has to be enabled explicitly.

At some point in the future, Don, I'd like to pick your brain about using trampolines like this for DDL.  I'd like to 
see cross-OS binaries become possible by thunking the exception-handling mechanisms between *nix and Win32 at link time, 
but I'm not sure how to pull that off just yet.

-- 
- EricAnderton at yahoo



More information about the Digitalmars-d mailing list