Forum > General
[SOLVED] Linker issue
MathMan:
Hi,
Environment: Lazarus 1.2.4 / FPC 2.6.4 / Win 7 64bit / Intel Core i5 430M @2.27 GHz
What do I have to do to convince the compiler to use 64 bit relocation for the inline assembler? Background is as follows.
I do keep some statistics counter in the general VAR definition
--- Code: ---unit Main;
...
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus;
type
...
var
LongCalc: TLongCalc;
Add_LLEU_Counter: QWORD; // Counter for calls to add low level
Add_LLEU_TotalTime: QWORD; // Total time spend (in CPU clocks)
Add_LLEU_LastTime: QWORD; // Time spend (in CPU clocks) on last call
Add_LLEU_MinTime: QWORD; // Lowest time spend on all calls
--- End code ---
When I access these from within the inline assembler like
--- Code: ---function Add_LLEU // Add Low Level Even Unsigned
(
Op1: pLimb; // first summand
Op2: pLimb; // second summand
Res: pLimb; // resulting sum
Size: QWORD // number of limb to work
):QWORD; // Carry
begin
{$IFNDEF ASM_VERSION} // Use Pascal only if assembly version is not avail
{$ifdef KEEP_STATS} // Inline statistics to be used
asm
rdtsc; // Read time-stamp-counter from core
shl RDX, 32; // Convert to 64 bit
or RAX, RDX;
mov qword ptr [Add_LLEU_LastTime], RAX; // Initialize this
inc qword ptr [Add_LLEU_Counter] // One more activation counted
end ['RAX', 'RDX'];
{$endif}
--- End code ---
I do get the linker warning on 32bit absolute relocation used
--- Code: ---LongCalculator.lpr(20,1) Warning: Object file "main.o" contains 32-bit absolute relocation to symbol ".bss.n_u_main_add_lleu_counter".
--- End code ---
This means that I can only reliably run the code in the lower 4GByte of a virtual address range. As long as I keep the debugger info included Windows will start the program as required - but as soon as I remove debug info the program gets executed above that space and consequently stops with a SIGSEGV.
Any ideas what I can do about this? I read what I could find in the documentation but couldn't find something usefull. Maybe there is doc available somewhere and I just haven't found it yet - linking me to where I should read on would then be highly appreciated.
Regards,
Jens
[02.08.2014] Edit: typos, rephrasing
MathMan:
Hi all again,
For all of you who'd like to see the solution (mainly my own stupidity) here's what happened and how I resolved it.
--- Quote from: MathMan on August 01, 2014, 11:24:55 pm ---Hi,
Environment: Lazarus 1.2.4 / FPC 2.6.4 / Win 7 64bit / Intel Core i5 430M @2.27 GHz
What do I have to do to convince the compiler to use 64 bit relocation for the inline assembler? Background is as follows.
...
--- End quote ---
Starting again with assembly language after >20 years revealed a lot of lost knowledge :-)
I completely forgot that the instruction set of x86 isn't very orthogonal so I initially tried to use combinations of instructions & addressing modes which simply aren't available. The inline assembler converted them to what is available (unfortunately a lot of things are ambiguous in assembly too) so it was finally the linker hinting me to what went wrong.
I started out with
--- Code: --- rdtsc; // Read time-stamp-counter from core
shl RDX, 32; // Convert to 64 bit
or RAX, RDX;
mov qword ptr [SHR_LL_LastTime], RAX; // Initialize this
inc qword ptr [SHR_LL_Counter] // One more activation counted
...
rdtsc; // Read time-stamp-counter from core
shl RDX, 32; // Convert to 64 bit
or RAX, RDX;
sub RAX, qword ptr [SHR_LL_LastTime]; // Now RAX is the delta
mov qword ptr [SHR_LL_LastTime], RAX; // Set last usage time
add qword ptr [SHR_LL_TotalTime], RAX; // Add to total time spend
cmp RAX, qword ptr [SHR_LL_MinTime]; // Do we have a new low?
cmovnc RAX, qword ptr [SHR_LL_MinTime]; // No => keep old
mov qword ptr [SHR_LL_MinTime], RAX; // Set accordingly
--- End code ---
What I forgot was that the addressing mode "offset64" (going to a full 64 bit address specified as an immediate value in the code) is - with respect to the above - only available for "mov" in connection with register RAX. After some fiddling I found the following replacement
--- Code: --- rdtsc; // Read time-stamp-counter from core
shl RDX, 32; // Convert to 64 bit
or RAX, RDX;
mov SHR_LL_LastTime, RAX; // Initialize this
mov RAX, SHR_LL_Counter; // One more activation counted
inc RAX
mov SHR_LL_Counter, RAX;
...
rdtsc; // Read time-stamp-counter from core
shl RDX, 32; // Convert to 64 bit in RDX
or RDX, RAX;
mov RAX, SHR_LL_LastTime;
sub RDX, RAX; // Now RDX is the delta
mov RAX, RDX; // Set last usage time
mov SHR_LL_LastTime, RAX;
mov RAX, SHR_LL_TotalTime; // Add to total time spend
add RAX, RDX;
mov SHR_LL_TotalTime, RAX;
mov RAX, SHR_LL_MinTime; // Do we have a new low?
cmp RDX, RAX;
cmovc RAX, RDX; // Yes => use it
mov SHR_LL_MinTime, RAX; // Set accordingly
--- End code ---
This one now eliminates the linker warnings and the produces code looks as intended.
I think I have to re-read the Intel reference guide carefully :-)
Regards,
Jens
marcov:
I assume that can be considered an assembler reader bug, so I reported it: http://bugs.freepascal.org/view.php?id=26555
MathMan:
--- Quote from: marcov on August 03, 2014, 01:46:53 pm ---I assume that can be considered an assembler reader bug, so I reported it: http://bugs.freepascal.org/view.php?id=26555
--- End quote ---
I don't think so. From assembler sources one can usually infer verry little because it could always be the case that the author intentionally did something in a special way. In my bogus code above all resulting addressing modes were completely legal - so the assembler had to make do with what is available (in this case use 32bit offset variants of certain menmonics). That this can lead to catastrophy when linked & executed in a pure 64bit environment is beyond recognition of the assembler.
What the assembler could do IMO is throw a warning that the used addressing mode does not correspond to the intended environment. But even this I would only do in a very verbose setting. When using assembler the hard work of knowing what you're doing resides with the author.
That's my view on the issue - even if I have spend two days tracking this down.
MathMan:
--- Quote from: marcov on August 03, 2014, 01:46:53 pm ---I assume that can be considered an assembler reader bug, so I reported it: http://bugs.freepascal.org/view.php?id=26555
--- End quote ---
I just followed your link and read the comments from Jonas - makes perfect sense. I'll rewrite so that I only do the access to the processor time stamp counter in assembler.
BTW: Bugtracker - I wanted to raise a bug myself for missing mnemonics (ADCX, ADOX). Now I have two questions regarding this
1 - I can't seem to login. Neither under my existing account nor can I register a new one. Is there something special required - e.g. allowing Cookies?
2 - Is there a documentation on the usage of bugtracker avail? Before I register a new bug I'd like to search existing ones so that I do not duplicate and the search functionality looks pretty arcane to me.
Regards,
Jens
Navigation
[0] Message Index
[#] Next page