Pelles C forum

Assembly language => Assembly discussions => Topic started by: jk on August 23, 2023, 08:33:52 PM

Title: polink issue ?
Post by: jk on August 23, 2023, 08:33:52 PM
By chance i came across this problem. I have an app, which tests error recovery features. Linking the . obj file with MS´s linker just works fine, using polink the resulting .exe crashes. Investigating this further i found that polink resolves the local label "__el1" incorrect as it seems (assembler snippet "error.asm" line 18). This label name ("__el1") occurs in more than one procedure, but this shouldn´t be a problem, because it is a local label. Polink makes the corresponding jump go into a different procedure to a label with the same name, which leads to GPF further on. The attached .obj file has got inserted an "int 3" before the offending "jmp" in order to be able to easily find the error location with a debugger. Please study the supplied files in the attachment.

Thanks

JK
Title: Re: polink issue ?
Post by: Vortex on August 24, 2023, 09:25:53 AM
Hi jk,

Could you please provide the complete source code so we can reproduce the issue?
Title: Re: polink issue ?
Post by: jk on August 24, 2023, 01:36:53 PM
The original source is assembler and i use a very special setup, which at the moment is WIP and therefore scattered all over my HD - could be a major task reproducing.

That is why i supplied the assembled .obj file. As said avove the error occurs when linking with polink, it doesn´t occur with MS´s linker from Visual Studio. MS´s stuff is overbloated for what i need, therefore i tried polink. It works perfectly well in all of my other apps, but it fails here (al least i suppose it´s a linker problem).

The attachement contains the .obj file, the resulting .exe files for polink.exe and link.exe (MS), the batch commandline for polink (incl. command file), two debugger screenshots and a snippet of the relevant assembler code. As you can see, this isn´t regular assembler code, among other things my setup maps e.g xax to eax and rax respectively, that is, the same code can be assembled in 32 and 64 bit.

As already said above, my current best bet is, that the jump address in line 18 of the snippet isn´t "calculated" correctly in the linking process, because the name of the label "__el1" is not unique. It is unique per procedure, but it is not unique all over the .obj file, because a label with same name is present in several procedures. I hope this is sufficient data to investigate what happens.
Title: Re: polink issue ?
Post by: John Z on August 24, 2023, 02:50:26 PM
Hi jk,

So have you tried to prove it is a multiple label name use issue by changing to unique names?
From what you said there should be no issue using unique names since they are supposed to
be procedure scoped.  And this should be a relatively minor edit.

Trying to figure out a potential bug from the output result files is much more difficult than starting
from the sources.  Perhaps you can created a demo version with just one or two procedures using
an identical 'local' label that shows the bug resulting in a link error.

John Z


Title: Re: polink issue ?
Post by: jk on August 24, 2023, 09:56:39 PM
I can confirm, that making the offending label name unique over all procedures makes the problem go away.

To my understanding the error occurs somewhere in the linking process, otherwise the executable linked with MS´s linker wouldn´t run properly. In the attachment of post #1 i supplied the . obj file, which is all you need for linking it yourself, as well as additional info as far as i could. I don´t see the advantage of being able to create the .obj file yourself, when you already have this .obj file. In my opinion only the developer(s) of polink can tell, what is wrong here.

I don´t claim that polink is buggy! But i have an .obj file which (when linked to an executable) works fine with MS´s linker and doesn´t with polink. So at first glance there are two options:
- it could be a bug inside the .obj file, but then it would be crucial to have this file for testing and finding out, what´s wrong with the .obj file
- it could be a bug in polink and then it is equally essential to have exactly this .obj file   
Title: Re: polink issue ?
Post by: TimoVJL on August 25, 2023, 11:18:54 AM
MAP-file might be useful for checking things ?
Title: Re: polink issue ?
Post by: frankie on August 25, 2023, 12:51:17 PM
I don't know exactly what is happening here, but I suppose that the result could be related at least to 2 different things.
The first is that the symbol, even if not declared global or extern, isn't considered 'local' by the compiler assembler (sorry, but I was used to C compiler  ;D).
The second point could be the recently added "select_any" behavior, introduced in version 11, that for multiply defined symbols simply pick one of them.
This is just a speculation  :P
Title: Re: polink issue ?
Post by: John Z on August 25, 2023, 02:12:34 PM
I've not done any Intel CPU assembly programing since the 486 came out ;( but looking to refresh my knowledge and for information I found this:
---
Labels

A label can be placed at the beginning of a statement. During assembly, the label is assigned the current value of the active location counter and serves as an instruction operand. There are two types of lables: symbolic and numeric.
Symbolic Labels

A symbolic label consists of an identifier (or symbol) followed by a colon (:) (ASCII 0x3A). Symbolic labels must be defined only once. Symbolic labels have global scope and appear in the object file's symbol table.

Symbolic labels with identifiers beginning with a period (.) (ASCII 0x2E) are considered to have local scope and are not included in the object file's symbol table.
---

If poasm/polink follows this rule then try putting a . in front of the labels that are to be local in scope. This should be easy to try .. the linker may be looking for this identifier.

John Z
reference link (maybe outdated) https://docs.oracle.com/cd/E26502_01/html/E28388/eqbsx.html
Title: Re: polink issue ?
Post by: jk on August 25, 2023, 09:37:44 PM
I can confirm, that it doesn´t depend on the version of polink, the problem occurs with V 9 as well as with the latest (just tested).

The term "label" alone might be ambiguos, in this case "label" means a jump target, a location in code, where absolute or conditional jumps go to. In assembler code these "labels" must end with a colon, labels with local (procedure) scope get one single colon (e.g. "label:"), global labels get two consecutive colons (e.g. "global_label::"). A dot as first charcater is not allowed, the first character can be an alphabetic character (a-z, A–Z) or any of these four characters: "@ _ $ ?"
Title: Re: polink issue ?
Post by: John Z on August 26, 2023, 11:06:38 AM
Well I'll throw out one more thought then let it be as I'm certainly no expert - Vortex where are you  ?? ;)

Pelles Help File:
"The assembler contains a parser for the IA32 (X86) and AMD64 (X86-64) architecture with a syntax similar to MASM, but there are deliberate differences since POASM is not intended to be an exact clone of MASM."

----
https://fragglet.github.io/dos-help-files/alang.hlp/x_cln__cln_.html
 "With the single colon, <label> has global scope within its
     module under the default OPTION NOSCOPED. Under OPTION SCOPED,
     <label> is LOCAL inside a PROC block and is global elsewhere.
     The <label> cannot be declared public.
 
     The double colon acts the same as the single colon except that
     <label> has global scope within its module, independent of OPTION
     SCOPED, and can be declared PUBLIC."
---
Art of Assembly Language chapter 12
https://www.plantation-productions.com/Webster/www.artofasm.com/DOS/ch12/CH12-1.html#HEADING1-9   
"By default, MASM 6.x treats statement labels (those with a colon after them) as local to a procedure.
MASM uses the following default scoping rules:

    By default, statement labels appearing in a procedure are local to that procedure.
    By default, all procedure names are public.
    By default, most other symbols are global.

Note that these rules apply to MASM 6.x only. Other assemblers and earlier versions of MASM follow different rules.

Overriding the default on the first rule above is easy - either use the option noscoped statement or use a double colon to make a label global. You should be aware, though, that you cannot make a local label public using the public or externdef directives. You must make the symbol global (using either technique) before you make it public."
----

Makes me believe poasm follows the first "default OPTION NOSCOPED", additionally the poasm help
file makes no mention of having options for NOSCOPED or SCOPED that I could find.

That's all folks ....

John Z
Title: Re: polink issue ?
Post by: jk on August 26, 2023, 11:08:48 AM
Ok, i boiled it down to the absolute minimum:

Code: [Select]

ExitProcess PROTO :DWORD
TESTME PROTO

includelib KERNEL32.LIB


.CODE


TESTME PROC USES EBX ESI EDI
;*************************************************************************************
;
;*************************************************************************************
LOCAL _res:XWORD


  xor eax, eax


__el1:
  test eax, eax
  jne L2


  lea ebx, __el1
  mov _res, ebx
  jmp L1   ;jmp to error handler


; some other code


L1:
  add eax, 1
  JMP _res


L2:


RET


TESTME ENDP


start PROC USES EBX ESI EDI
;*************************************************************************************
;
;*************************************************************************************
LOCAL _res:XWORD


  invoke TESTME


int 3
  xor edx, edx


__el1:
  test edx, edx
  jne L2


  lea ebx, __el1
  mov _res, ebx
  jmp L1   ;jmp to error handler


; some other code


L1:
  add edx, 1
  JMP _res


L2:

INVOKE ExitProcess, edx


start ENDP


END start



Regardless which assembler i use (ml.exe, asmc.exe, uasm.exe) linking with MS´s link.exe works, linking with polink leads to error (see attachments)
Title: Re: polink issue ?
Post by: jk on August 26, 2023, 11:13:23 AM
Seems the attached images got lost
Title: Re: polink issue ?
Post by: John Z on August 26, 2023, 11:18:17 AM
Great -

Seems you did not try poasm?  I don't see it mentioned.
If poasm only uses default NOSCOPED then polink which
is written for poasm would not be expecting otherwise so
linking with polink but using other asm programs would be
an incompatibility.  The three assemblers below I expect are
highly compatible with MASM 6.1

John Z
Title: Re: polink issue ?
Post by: Vortex on August 26, 2023, 11:31:54 AM
Hi Jk,

A question :

Code: [Select]
TESTME PROC USES EBX ESI EDI
;*************************************************************************************
;
;*************************************************************************************
LOCAL _res:XWORD


  xor eax, eax


__el1:
  test eax, eax
  jne L2


  lea ebx, __el1
  mov _res, ebx
  jmp L1   ;jmp to error handler


; some other code


L1:
  add eax, 1
  JMP _res

What is XWORD?
Title: Re: polink issue ?
Post by: Vortex on August 26, 2023, 11:57:50 AM
Hi Jk,

After replacing the XWORDs with DWORDs, I managed to assemble your source code with Poasm. Disassembling the object module with Agner Fog's objconv :

Code: [Select]
.386
option dotname
.model flat

public _TESTME@0
public _start@0

extern _ExitProcess@4: near

@feat.00 equ 00000001H                                 


.drectve SEGMENT BYTE PUBLIC 'CONST'                   

        db 2FH, 64H, 65H, 66H, 61H, 75H, 6CH, 74H       
        db 6CH, 69H, 62H, 3AH, 4BH, 45H, 52H, 4EH       
        db 45H, 4CH, 33H, 32H, 2EH, 4CH, 49H, 42H       
        db 20H, 2FH, 65H, 6EH, 74H, 72H, 79H, 3AH       
        db 73H, 74H, 61H, 72H, 74H, 40H, 30H, 20H       

.drectve ENDS

_text   SEGMENT PARA PUBLIC 'CODE'                     

_TESTME@0 PROC NEAR
        push    ebp                                     
        mov     ebp, esp                               
        sub     esp, 4                                 
        push    ebx                                     
        push    esi                                     
        push    edi                                     
        xor     eax, eax                               

TESTME.__el1 LABEL NEAR
        test    eax, eax                               
        jnz     ?_002                                   
        lea     ebx, [TESTME.__el1]                     
        mov     dword ptr [ebp-4H], ebx                 
        jmp     ?_001                                   

?_001:  add     eax, 1                                 
        jmp     dword ptr [ebp-4H]                     
_TESTME@0 ENDP

?_002   LABEL NEAR
        pop     edi                                     
        pop     esi                                     
        pop     ebx                                     
        leave                                           
        ret                                             

_start@0 PROC NEAR
        push    ebp                                     
        mov     ebp, esp                               
        sub     esp, 4                                 
        push    ebx                                     
        push    esi                                     
        push    edi                                     
        call    _TESTME@0                               
        int     3                                       
        xor     edx, edx                               

start.__el1 LABEL NEAR
        test    edx, edx                               
        jnz     ?_004                                   
        lea     ebx, [start.__el1]                     
        mov     dword ptr [ebp-4H], ebx                 
        jmp     ?_003                                   

?_003:  add     edx, 1                                 
        jmp     dword ptr [ebp-4H]                     
_start@0 ENDP

?_004   LABEL NEAR
        push    edx                                     
        call    _ExitProcess@4                         
        pop     edi                                     
        pop     esi                                     
        pop     ebx                                     
        leave                                           
        ret                                             

_text   ENDS

END

Could you please show the issue(s) here in this output?

Listing the symbols of the object module :

Code: [Select]
E:\PellesC\Bin>podump.exe /SYMBOLS test.obj

Dump of erol.obj

File type: OBJ

SYMBOL TABLE
0000 00000001 ABS    notype      static       | @feat.00
0001 00000000 SECT1  notype      static       | .drectve
     length of section   28, #relocations    0, #linenumbers    0
0003 00000000 SECT2  notype      static       | .text
     length of section   57, #relocations    3, #linenumbers    0
0005 00000000 UNDEF  notype      external     | _ExitProcess@4
0006 00000000 SECT2  notype ()   external     | _TESTME@0
0007 00000025 SECT2  notype ()   external     | _start@0
0008 0000000B SECT2  notype      static       | TESTME.__el1
0009 00000037 SECT2  notype      static       | start.__el1

SUMMARY
      28 .drectve
      57 .text

Removing the instruction int 3, I rebuilt the application. A session of Ollydbg didn't report any issues.
Title: Re: polink issue ?
Post by: jk on August 26, 2023, 05:20:26 PM
My bad, it should have been "DWORD" (my setup maps XWORD to DWORD/QWORD in 32/64 bit respectively)

This is what i get with podump:
Code: [Select]
Dump of Test.obj

File type: OBJ

SYMBOL TABLE
0000 00000000 DEBUG  notype      filename     | .file
     C:\Users\Juergen\Desktop\Pelle\Test.tmp
0004 00000000 SECT1  notype      static       | .text
     length of section   53, #relocations    3, #linenumbers    0
0006 00000000 SECT2  notype      static       | .data
     length of section    0, #relocations    0, #linenumbers    0
0008 00000000 SECT3  notype      static       | .drectve
     length of section   28, #relocations    0, #linenumbers    0
000A 00000000 UNDEF  notype ()   external     | _ExitProcess@4
000B 00000000 SECT1  notype ()   external     | _TESTME@0
000C 00000027 SECT1  notype ()   external     | _start@0
000D 0000000B SECT1  notype      label        | ___el1
000E 00000038 SECT1  notype      label        | ___el1


The offending line in your disassembly is:
Code: [Select]
lea     ebx, [start.__el1]
which is correct, so no problem here

Assembling it with the other assemblers and linking it with polink results in this (as if the code in start proc would have been like so):
Code: [Select]

lea     ebx, [TESTME.__el1]

Obviously poasm creates symbols in a different way and polink expects such symbols ...

As you can see in my dump, the symbol "___el1" is listed twice and there isn´t a prefix indicating the corresponding procedure, which, as it seems, polink needs to get things straight, while MS´s linker can handle it nevertheless.

So definitely not a bug, because polink is tailored for po...  things, but because of these special things polink cannot be used for linking everything.

Maybe i´m still overlooking something...  A pity - polink would have been a lightweight alternative to MS´s bloated stuff. Anyway, thanks for your help and contributions!
Title: Re: polink issue ?
Post by: frankie on August 26, 2023, 06:37:24 PM
So definitely not a bug, because polink is tailored for po...  things, but because of these special things polink cannot be used for linking everything.

Maybe i´m still overlooking something...  A pity - polink would have been a lightweight alternative to MS´s bloated stuff. Anyway, thanks for your help and contributions!
Good to know that the issue is solved.  :)
I'll remove it from the bug reports thread to avoid confusion.
Anyway it's always unsafe to expect that MS things are conformant to any standard...  ;D
Title: Re: polink issue ?
Post by: John Z on August 26, 2023, 08:29:03 PM
Good work Vortex!  Thanks for answering the call  :) :) :)

John Z
Title: Re: polink issue ?
Post by: Vortex on August 26, 2023, 09:41:00 PM
Hi John,

You are welcome, thanks.

Hi jk,

It would be preferable to give unique and more descriptive names to your labels to avoid conflicts.

Assembling the code with MS Macro Assembler supplied with the Masm32 package :

Code: [Select]
E:\PellesC\Bin>\masm32\bin\ml.exe /c /coff test.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: test.asm

Trying to link the object module with Polink :

Code: [Select]
E:\PellesC\Bin>polink.exe /SUBSYSTEM:WINDOWS test.obj \PellesC\lib\Win\kernel32.lib
POLINK: error: Symbol '__el1' is multiply defined: 'test.obj' and 'test.obj'.

The output of MS Macro Assembler :

Code: [Select]
_TESTME@0 PROC NEAR
        push    ebp                                     ; 0000 _ 55
        mov     ebp, esp                                ; 0001 _ 8B. EC
        add     esp, -4                                 ; 0003 _ 83. C4, FC
        push    ebx                                     ; 0006 _ 53
        push    esi                                     ; 0007 _ 56
        push    edi                                     ; 0008 _ 57
        xor     eax, eax                                ; 0009 _ 33. C0

__el1   LABEL NEAR
        test    eax, eax                                ; 000B _ 85. C0
        jnz     ?_002                                   ; 000D _ 75, 11
        lea     ebx, [__el1]                            ; 000F _ 8D. 1D, 00000000(d)
        mov     dword ptr [ebp-4H], ebx                 ; 0015 _ 89. 5D, FC
        jmp     ?_001                                   ; 0018 _ EB, 00

?_001:  add     eax, 1                                  ; 001A _ 83. C0, 01
        jmp     dword ptr [ebp-4H]                      ; 001D _ FF. 65, FC
_TESTME@0 ENDP

?_002   LABEL NEAR
        pop     edi                                     ; 0020 _ 5F
        pop     esi                                     ; 0021 _ 5E
        pop     ebx                                     ; 0022 _ 5B
        leave                                           ; 0023 _ C9
        ret                                             ; 0024 _ C3

_start@0 PROC NEAR
        push    ebp                                     ; 0025 _ 55
        mov     ebp, esp                                ; 0026 _ 8B. EC
        add     esp, -4                                 ; 0028 _ 83. C4, FC
        push    ebx                                     ; 002B _ 53
        push    esi                                     ; 002C _ 56
        push    edi                                     ; 002D _ 57
        call    _TESTME@0                               ; 002E _ E8, FFFFFFCD
        xor     edx, edx                                ; 0033 _ 33. D2

__el1   LABEL NEAR
        test    edx, edx                                ; 0035 _ 85. D2
        jnz     ?_004                                   ; 0037 _ 75, 11
        lea     ebx, [__el1]                            ; 0039 _ 8D. 1D, 00000000(d)
        mov     dword ptr [ebp-4H], ebx                 ; 003F _ 89. 5D, FC
        jmp     ?_003                                   ; 0042 _ EB, 00
Title: Re: polink issue ?
Post by: TimoVJL on August 28, 2023, 10:01:05 AM
I tried ml (2013) with -Gy option and result crashed.
Code: [Select]
.386
.model flat, stdcall

ExitProcess PROTO :DWORD
TESTME PROTO

includelib KERNEL32.LIB


.CODE


TESTME PROC USES EBX ESI EDI
;*************************************************************************************
;
;*************************************************************************************
LOCAL _res:DWORD


  xor eax, eax


__el1:
  test eax, eax
  jne L2


  lea ebx, __el1
  mov _res, ebx
  jmp L1   ;jmp to error handler


; some other code


L1:
  add eax, 1
  JMP _res


L2:


RET


TESTME ENDP


start PROC USES EBX ESI EDI
;*************************************************************************************
;
;*************************************************************************************
LOCAL _res:DWORD


  invoke TESTME


int 3
  xor edx, edx


__el1:
  test edx, edx
  jne L2


  lea ebx, __el1
  mov _res, ebx
  jmp L1   ;jmp to error handler


; some other code


L1:
  add edx, 1
  JMP _res


L2:

INVOKE ExitProcess, edx
  ret

start ENDP


END start

Code: [Select]
00000000  55                       push ebp
00000001  8BEC                     mov ebp, esp
00000003  83C4FC                   add esp, -4h
00000006  53                       push ebx
00000007  56                       push esi
00000008  57                       push edi
00000009  33C0                     xor eax, eax
0000000B  85C0                     test eax, eax
0000000D  7511                     jnz L_20
0000000F  8D1D0B104000             lea ebx, [$+40100Bh]
00000015  895DFC                   mov dword ptr [ebp-4h], ebx
00000018  EB00                     jmp L_1A
0000001A  83C001                   add eax, 1h
0000001D  FF65FC                   jmp dword ptr [ebp-4h]
00000020  5F                       pop edi
00000021  5E                       pop esi
00000022  5B                       pop ebx
00000023  C9                       leave
00000024  C3                       ret
00000025  CC                       int3
00000026  CC                       int3
00000027  CC                       int3
00000028  55                       push ebp
00000029  8BEC                     mov ebp, esp
0000002B  83C4FC                   add esp, -4h
0000002E  53                       push ebx
0000002F  56                       push esi
00000030  57                       push edi
00000031  E8CAFFFFFF               call $-31h
00000036  CC                       int3
00000037  33D2                     xor edx, edx
00000039  85D2                     test edx, edx
0000003B  7511                     jnz L_4E
0000003D  8D1D39104000             lea ebx, [$+401039h]
00000043  895DFC                   mov dword ptr [ebp-4h], ebx
00000046  EB00                     jmp L_48
00000048  83C201                   add edx, 1h
0000004B  FF65FC                   jmp dword ptr [ebp-4h]
0000004E  52                       push edx
0000004F  E806000000               call $+Bh
00000054  5F                       pop edi
00000055  5E                       pop esi
00000056  5B                       pop ebx
00000057  C9                       leave
00000058  C3                       ret
00000059  CC                       int3
0000005A  FF2500204000             jmp dword ptr [$+402000h]
Title: Re: polink issue ?
Post by: Vortex on August 29, 2023, 07:28:03 PM
Source code assembled with ml V14.29.30151.0 and object file linked with link V5.12.8078. No any crash.
Title: Re: polink issue ?
Post by: TimoVJL on August 30, 2023, 03:23:28 PM
test was done with 14.33.31630.0
hopefully test asm source was same as i used and isn't reason for crash.
no downloads, so not with same source.