News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

position independent code in masm

Started by markallyn, December 25, 2017, 05:34:29 AM

Previous topic - Next topic

markallyn

Hello everyone,

As far as I can tell this is a new post.  Apologies if my question has been answered previously.

In MASM/Windows how is position independent code (pic or pie) written?   How does MASM/Windows achieve position independence?  I can find no references on this subject and hoped that an expert might be able to explain what's happening.  In the linux world the Global Offset Table plays a critical role, but as far as I know or have read, this table does not exist in the MSFT/Windows world.  Yet somehow the problem is plainly solved.

Thanks for any enlightenment.

Mark Allyn

hutch--

Hi Mark,

A library module is the format that will do what you need. Any data needed by the module must be passed to it unless it get the data independently within the module. Just as an example, a Windows app has an instance handle that is required by many API functions. You can either get it once at startup and put it into a GLOBAL scope variable OR as I have seen often you call the API every time you need it. I prefer the former as the latter is un-necessary code duplication.

To make a procedure position independent, it must have access to all of the data it needs, either by arguments passed to it or functions it can call to get the data. A common one in Windows is "GetParent()" where you need the handle of a parent window for a control (interface component) which is a child window to the parent.

markallyn

Good afternoon/evening Hutch,

If I understood you correctly, there is no concept of a GOT/PLT analog implemented in MASM/Windows.  Rather, the same results are obtained by a completely different technique.  I wonder why Linux/Unix followed the path it did.  It certainly increased the complexity of code when I fooled around with it.

On a related note, as far as I can tell, RIP-relative addressing is forbidden in MASM64, at least it complained when I tested it.  I found only a single proposal as to why MASM64 doesn't whereas at least two other "ASMs" do, namely for "security reasons",  I am not well-enough versed to understand why this might be so.

At any rate, thank you for responding.  Very helpful as always.

Mark

jj2007

See the RIP-relative addressing thread. UAsm supports it afaik.
I haven't checked About RIP relative addressing but it looks interesting, too.

hutch--

With the advent of x64 with the extra registers I stay away from the stack pointer, base pointer and instruction pointer as it makes for dangerous code with no gain. Outside of some potential OS tasks that may benefit from direct manipulation of the instruction pointer (RIP) I don't see it being of much use in application code. It was common in 32 bit code to write procs with no stack frame so you could use EBP after you preserved it and if you liked living dangerously you could use ESP as well but with twice as many registers in x64 you don't have to bother doing risky things. It means you can leave the stack alone which keeps your code reliable and simple.

aw27

In 64-bit, all addressing is RIP-Relative, although you can force in some cases it not to be.
This makes it easy to make PIC code, when such code does not address data & code relocated by the loader.
That is, if you move a block of code to another address you can:
1- jump to labels or call functions within the moved block as if nothing had happened.
2- you can save and access data on the stack as if nothing happened.
2- You can use library functions only with LoadLibrary/GetProcAddress.
3- You can not access any data in the .data section, unless you do a recalculation of relative positions.

In 32-bit most calls and jumps are also relative, i.e near calls, so in general restrictions for 32 bit are the same as for 64-bit

markallyn

JJ-

I checked the second link you sent and played with the author's examples a bit.  I think he shows that ml64 cannot assemble a [rip] operand.  However, if you hard code the instruction and avoid the assembler then you can indeed access the rip.  So, if you know the hard code -- and I certainly don't -- you can use ml64 for all the non-rip instructions and insert the hard code as needed.

Thanks,
Mark

jj2007

Quote from: markallyn on December 26, 2017, 05:03:49 AMSo, if you know the hard code -- and I certainly don't -- you can use ml64 for all the non-rip instructions and insert the hard code as needed.

You could build it with UAsm first, then run the exe with a disassembler, so that you can see the hard code that you need for ML64 :t

hutch--

 :biggrin:

You could probably look it up in the Intel manual as well, save playing with other toys.

markallyn

Good morning/afternoon/evening Hutch and JJ,

I didn't know about UASM, but was familiar with Jwasm (and some of its many options).  Anyway, I downloaded and played with uasm and indeed it does support rip-relative addressing.  Thanks for putting me on to it.

To Hutch's point:  using one assembler to get hard codes for another does seem like a pretty ugly way to do it.  Perhaps "ugly" is too strong an adjective?  It works, however.  Going to the INTEL manuals seems the only alternative and I suppose it has the virtue of forcing one to learn more about constructing machine codes.

Regards,
Mark