flat assembler
Message board for the users of flat assembler.

Index > Main > Multiple passes vs. relocations

Author
Thread Post new topic Reply to topic
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Hello, everybody. I was trying to answer a question of another fasm user and failed to find a solution. The point is to make fasm generate some relocation demanding data if and only if no other relocations need to be generated.

The following code will clearly not compile because of mutually exclusive requirements:
Code:
format PE GUI 4.0

entry start

section '.code' data readable executable

start:

ret

align 4
;dd $

if relocs_size = 0
  dd $
end if

section '.reloc' fixups data discardable
relocs_size = $-$$
    

An obvious workaround can be found in the documentation:
Code:
format PE GUI 4.0

entry start

section '.code' data readable executable

start:

ret

align 4
;dd $

if relocs_size = 0 | defined safe_relocs
        safe_relocs dd $
end if

section '.reloc' fixups data discardable
relocs_size = $-$$    

The problem is that after uncommenting the first dd $ definition the second dd $ definition is still included into the binary which is undesirable.

Even making the solution with both definitions invalid does not make fasm find an alternative correct solution. The following code fails to compile even though a correct solution is just not define safe_relocs.
Code:
format PE GUI 4.0

entry start

section '.code' data readable executable

start:

ret

align 4
dd $

if relocs_size = 0 | defined safe_relocs
     rb 10-relocs_size
   safe_relocs dd $
end if

section '.reloc' fixups data discardable
relocs_size = $-$$    


Is there any possibility to make fasm find the correct solution?

Best regards
Post 15 Sep 2011, 15:38
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17270
Location: In your JS exploiting you and your system
revolution
I use this code under WinXPSP2:
Code:
format PE GUI 4.0

entry start

section '.code' data readable executable

start:  ret

section '.reloc' data discardable

data fixups
   if ~ $-$$
           dd      0,8 ;empty fixups section iff no other fixups
       end if
end data    
I find it useful for DLLs that have no fixups. Windows refuses to load DLLs that have no fixups table.
Post 15 Sep 2011, 15:48
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
revolution
Well... Thank you. I thought about creating relocations manually. A little bit nasty, but seems to be the only working solution.
Post 15 Sep 2011, 16:02
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
Wow, this one is complex. Smile I will try to explain why your method failed. First, the default value assumed for variable not yet defined (in the very first pass) is 0, so "relocs_size = 0" is true in first pass and causes "safe_relocs" to be defined. We could try to correct it this way:
Code:
if inverse_relocs_size = 0FFFFFFFFh | defined safe_relocs
; ...
inverse_relocs_size = dword not ($-$$)    
But this will not work in this specific case, because of the way in which fasm generates PE relocations - only after it sees that the "fixups" section/data is put into output code, it changes the code type to relocatable (this has an impact on how code is generated - some instructions cannot be optimized to shorter forms) and so the fixups data is gathered starting from the following pass. Thus in first pass relocs_size is assumed to be 0 (because it was not yet defined) and '.reloc' section is empty because no fixups were yet gather. So in second pass relocs_size is 0FFFFFFFFh and we land inside "if" anyway (and then the solution is found with self-fulfilling "safe_relocs" definition).

So a different approach is needed in this case. We can, for example, exploit the fact that section with just one fixup is 10 bytes in length:
Code:
if relocs_size = 0 | (defined safe_relocs & relocs_size = 10)
        safe_relocs dd $
end if    
and this will make sure that "safe_relocs" will only be defined when no other fixup is generated.

revolution's solution is much nicer though. I definitely recommend to do it revolution's way.
Post 15 Sep 2011, 16:19
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Tomasz Grysztar
Quote:
Code:
if relocs_size = 0 | (defined safe_relocs & relocs_size = 10) 
        safe_relocs dd $ 
end if    

Thank you! That's exactly, what I was trying to do, but failed to achieve because of some knowledge lack. E.g. undefined variable value defaulting to zero is not documented anywhere, is it?
Quote:
revolution's solution is much nicer though. I definitely recommend to do it revolution's way

Why not making an empty relocations table to be compiled to dd 0,8? As revolution mentioned, zero-sized sections are not accepted by windows loader and thus make no sense.
Post 15 Sep 2011, 17:39
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
Well, it was discussed before: http://board.flatassembler.net/topic.php?p=33127#33127 (note the Win9x vs WinNT difference, too).
Post 15 Sep 2011, 17:53
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Tomasz Grysztar
I meant the relocation table, not the relocation section. And dd 0,8 does not mean creation of a dummy block, it really means an empty relocations table with no blocks. Thus padding of any section to achieve non-zero-sized-section is quite normal, because it's the programmer's responsibility to create or to omit section creation. But padding of a relocation table makes no-relocations-case to some special case, whereas making this code:
Code:
data fixups
end data    

to be compiled as dd 0,8 makes no-relocations-case as regular as any other case.
Post 15 Sep 2011, 18:15
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
Please read the whole thread I linked to.
Post 15 Sep 2011, 18:20
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Tomasz Grysztar
Sorry. What I wrote before:
Quote:
And dd 0,8 does not mean creation of a dummy block, it really means an empty relocations table with no blocks.

is not true. My mistake.
Post 15 Sep 2011, 18:41
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17270
Location: In your JS exploiting you and your system
revolution
l_inc wrote:
But padding of a relocation table makes no-relocations-case to some special case, whereas making this code:
Code:
data fixups
end data    

to be compiled as dd 0,8 makes no-relocations-case as regular as any other case.
I am inclined to agree here. User has told fasm to generate a fixup table but fasm has said "Nope, I won't do it. Instead I will do nothing at all."
Post 16 Sep 2011, 03:19
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
Not true that it does nothing - it creates an empty relocation table which you can fill out yourself if you need (just like any other case of "data" directive, in fact).
Also, as mentioned in that other thread, empty relocations directory is not something wrong by itself - though some Windows versions did have problems with it, others don't.

Code:
BASE = 1000000h

format PE at BASE
org BASE

; ...


data fixups
; DIY fixups
end data    
Post 16 Sep 2011, 07:36
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17270
Location: In your JS exploiting you and your system
revolution
Tomasz Grysztar wrote:
Code:
data fixups
; DIY fixups
end data    
The DIY thing is really only applicable when there are no fixups. If there were some way to stop fasm from automatically inserting the fixups then it would be a true DIY:
Code:
data fixups_without_auto_generation
 ;My fixus go here
end data    
On another matter I did some testing and see that you are right about WinXP at least, it can accept a zero sized fixup table. This assembles and loads fine.
Code:
format    PE GUI 4.0 DLL
entry start
section        '' data readable executable
start:     ret
data     fixups
end   data    
I never realised this before and now I forget which OS fails on the zero sized fixup table. I expect it was Win95 but I don't have a system around to test that now.
Post 16 Sep 2011, 08:35
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
revolution wrote:
If there were some way to stop fasm from automatically inserting the fixups then it would be a true DIY:

That's what the "org BASE" line in my example is for.
...but I made a mistake, it really should have been:
Code:
org BASE + rva $    

Because you've got non-zero RVA right from the start.

The trick lies in the fact that "BASE + rva $" is an absolute value equivalent to unrelocated "$". So starting from that point you define absolute addresses, and fasm has no relocations to make.
Post 16 Sep 2011, 08:53
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17270
Location: In your JS exploiting you and your system
revolution
Tomasz Grysztar wrote:
That's what the "org BASE" line in my example is for.
I didn't know that. I keep learning new things about fasm on a regular basis. Smile
Post 16 Sep 2011, 09:24
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
Tomasz Grysztar wrote:
Well, it was discussed before: http://board.flatassembler.net/topic.php?p=33127#33127 (note the Win9x vs WinNT difference, too).


And here http://board.flatassembler.net/topic.php?t=11170
Post 18 Sep 2011, 08:53
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar.

Powered by rwasa.