News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

HJWasm .SWITCH - .CASE - .DEFAULT - .ENDSWITCH

Started by habran, April 10, 2016, 08:26:42 PM

Previous topic - Next topic

jj2007

Quote from: habran on April 17, 2016, 06:11:41 AMHSE, I do programming only in 64 bit and that is why I was not aware that since the first HJWasm /Zi doesn't work for 32 bit.
I know that most of the people who still do programming in 32 bit use Olly for debugging and they don't care about source level debugging

Source level debugging is possible with Olly, but with macros it makes little sense. Most people would use symbolic debugging, though, and that works with HJWasm32 (version 11 April):

include \masm32\MasmBasic\MasmBasic.inc      ; download
.data
MyQ      QWORD 1234567812345678h

  Init
  int 3
  Print Str$("The value is %i\n", MyQ)
  Inkey "Assembler used: ", AsmUsed$()
EndOfCode


0040107C             ³.  CC                 int3
0040107D             ³.  8D05 00704000      lea eax, [MyQ]
00401083             ³.  50                 push eax
00401084             ³.  6A 05              push 5
00401086             ³.  6A 30              push 30
00401088             ³.  68 58704000        push offset ra_lbl2                ; ASCII "The value is %i\n"
0040108D             ³.  E8 04020000        call Float2Asc
00401092             ³.  6A 7F              push 7F
00401094             ³.  6A 01              push 1
00401096             ³.  E8 38100000        call MbPrint
0040109B             ³.  68 6C704000        push offset ra_lbl3                ; ASCII "Assembler used: "
004010A0             ³.  68 80704000        push offset ra_lbl4                ; ASCII "HJWasm32"
004010A5             ³.  6A 22              push 22
004010A7             ³.  E8 27100000        call MbPrint


habran

I know now for certain that these two lines in 32 bit cause general failure error but why only in 32 bit and why they still create proper code, I have no idea
I wish that someone enlighten me
Quote
          if (ModuleInfo.Ofssize == USE64){
            AddLineQueueX("lea  rdx,%s", GetLabelStr(hll->labels[LDATA2], buff));this is OK
            AddLineQueueX("movzx  rax,BYTE PTR[rdx+rax]");
            AddLineQueueX("lea  rdx,%s", GetLabelStr(hll->labels[LDATA1], buff));this is OK
            AddLineQueueX("jmp  QWORD PTR[rdx+rax*8]");
          }
          else{
            AddLineQueueX("lea  edx,%s", GetLabelStr(hll->labels[LDATA2], buff)); ERROR
            AddLineQueueX("movzx  eax,BYTE PTR[edx+eax]");
            AddLineQueueX("lea  edx,%s", GetLabelStr(hll->labels[LDATA1], buff));ERROR
            AddLineQueueX("jmp  DWORD PTR[edx+eax*4]");
          }
Cod-Father

jj2007

They look identical. How is the general failure triggered? SEH? Switch it off and let it crash...

fearless

Maybe double check to see what is in ModuleInfo.Ofssize if it is != USE64, as in the branch that fails, double check to see its not some other value relevant to 16bit or some other definition that is the same as 64bit. Might explain the crashing then if some other value is passed and your assuming its for 32bit where in fact it might be still related to 64bit code? dunno if that makes sense, but hopefully verifying what is in ModuleInfo.Ofssize might help

habran

Thanks fearless, :biggrin:
I tried that already but did not help :(
Cod-Father

jj2007

You have a compiler that spits out "general failure". There must be code that ends up in the line printf("general failure"). Find out at which point the code jumps there. Insert a printf("error code=%i", retval), or an INT 3.
My best guess is it's an exception handler. Exception handlers can be commented out or switched off, and your just-in-time debugger will tell you precisely where the exception happens.

Btw it would help to have a short example of code failing with "general failure", together with the settings used (/Zi? /Zf?) with a link to the exact HJWasmxxx version that can't handle that code. Right now I've tried a lot but can't convince HJWasm32.exe to shout "general failure".

habran

Hi JJ2007,
This attached folder contains the source and HJWasm32
If you build with /Zi or /Zd it will throw the General Failure error

This is a debug version of HJWasm
release version throws the same error even if you not build with /Zi

Let see if you can find why

Keep in mind that 64 bite works fine, that means that somewhere data is misinterpreted



Cod-Father

habran

The bug is here in linnum.c  line 58 but what causes it is a question:

First-chance exception at 0x010593AB in HJWasm.exe: 0xC0000005: Access violation writing location 0x00FEEB04.
Unhandled exception at 0x010593AB in HJWasm.exe: 0xC0000005: Access violation writing location 0x00FEEB04.

Quote
static void AddLinnumData( struct line_num_info *data )
/*****************************************************/
{
    struct qdesc *q;
#if COFF_SUPPORT
    if ( Options.output_format == OFORMAT_COFF ) {
        q = (struct qdesc *)CurrSeg->e.seginfo->LinnumQueue;
        if ( q == NULL ) {
            q = LclAlloc( sizeof( struct qdesc ) );
            CurrSeg->e.seginfo->LinnumQueue = q;
            q->head = NULL;
        }
    } else
#endif
        q = &LinnumQueue;

    data->next = NULL;
    if ( q->head == NULL)
        q->head = q->tail = data;
    else {
        ((struct line_num_info *)q->tail)->next = data;             // here is the bug
        q->tail = data;
    }
}
Cod-Father

jj2007

Quote from: habran on April 18, 2016, 08:40:09 PMThis is a debug version of HJWasm

Unfortunately, it won't run on Win7-64 - msvcrt120d.dll missing...

One debugging technique that I use often in bigger packages is to use a global variable to break. In assembler code:

.if globaldebug==123
  mov globaldebug, 0   ; use the flag only once
  INT 3   ; allow JIT debugger to break here
.endif

Then, in the source, you use mov globaldebug, 123 before the region where you suspect the problem. For example, if you know the general failure happens here:

  mov eax,'ABCF'
   NoP     ; hijack the nop handler
   .switch eax
     .case 'ABCC'     ; <<<< it happens here
     mov  edx,'ABCG'
     .break


... then use a globaldebug=123; where you handle the nop instruction, if and only if the case-sensitive nop happens to be NoP (which no sane coder would use).

Should be possible in C. The bug looks like a de-referencing problem, but I am no good at C, and can't see the q/tail/next etc structure either. Btw isn't next a reserved word?

P.S.: Under the hood...

asm("int $3");
        ((struct line_num_info *)q->tail)->next = data;
asm("nop");
        q->tail = data;
asm("nop");


00428A54             ³.  CC                 int3
00428A55             ³.  8B43 04            mov eax, [ebx+4]
00428A58             ³.  8930               mov [eax], esi
00428A5A             ³.  90                 nop
00428A5B             ³.  8973 04            mov [ebx+4], esi    <<<<<<<<< CRASH
00428A5E             ³.  90                 nop


habran

Thank you JJ for such a detailed info :t
Actually, in VS debugger I can break in that peace of code and see all variables contests, however, you know from the life experience about the cause and effect:  the effect is here but the cause is hiding somewhere else
The cause is what I am looking for :dazzled:
Cod-Father

jj2007

Quote from: habran on April 18, 2016, 11:59:55 PM
The cause is what I am looking for :dazzled:

printf("q=%x\t", q);
printf("q  tail=%x\n", q->tail);
        ((struct line_num_info *)q->tail)->next = data;
        q->tail = data;


Result:
...
q=4b0230        q  tail=4b0788
q=4b0230        q  tail=4b0798
q=4b0230        q  tail=4b07a8
q=4b0230        q  tail=4b07b8
q=4b0230        q  tail=4b07c8
q=4b0230        q  tail=4b0700
q=4b0230        q  tail=feebe8


4bnnnn looks like heapalloc'ed addresses. The last one, feebe8, is something like BAAD F00D  8)

habran

Yeah, I know that, that is the effect but what is the cause :(
I mean, why is there BAAD F00D???
I think that even 4b0700 is already wrong address, it suppose to be 4b07d8
We have to find the MF diversant (the function) who put it there :badgrin:
Cod-Father

TWell

#87
How myatoi128() handle that .case 'ABCD' ?
hll.c in GitHub crash after that ?
In debug builds pointer hll is destroyed at some point after myatoi128().
If i put hll = HllStack; after myatoi128() call, i can avoid crash :icon_confused:
or if i move uint_64             n; after int                 j;:icon_confused:

habran

Hi TWell,
That HJWasm in repository can not handle the 'ABCD' yet, this is a new feature which will be in the next upload
We did not upload it yet because of that /Zi problem in 32 bit
myatoi128 doesn't handle it, this is a routine that does:
we have added at the top of the function 3 additional vars:
  uint_64           dst[1];
  int                   a;
  uint_8              c;

Quote
    j = strlen(buffer);
    if (buffer[0] == 0x27){  // 0x27 = ''' EG: 'ABCD'
      a = 1;                        // skip '''
      dst[0] = 0;                 // zero it before use
      while (a < j){             
        c = buffer[a];           // read 1 byte at the time
        if (c == 0x27)          // ''' ? is it the end
          break;                   // finish
       dst[0] <<= 8;          // make space for next byte
       dst[0] |= c;              // add at the end a new char
       a++;                       // increase a counter
      }
      n = dst[0];               put the result in n variable
    }
    else if ((buffer[j-1] | 0x20) == 'h' )
      myatoi128( buffer, &n, 16, j-1);
#if CHEXPREFIX
    else if (((buffer[1] | 0x20)== 'x') && (*buffer == '0'))
      myatoi128( buffer, &n, 16, j-2);
#endif
    else
      myatoi128( buffer, &n, 10, j);
    pcases[hll->casecnt] = (int_32)n;
    myatoi128( buff+2, &n, 16, 4);
    plabels[hll->casecnt] = (uint_16)n;
    hll->casecnt++;
     break;
Cod-Father

jj2007

linnum.c:

static void AddLinnumData( struct line_num_info *data )
/*****************************************************/
{
    struct qdesc *q;
#if COFF_SUPPORT
    if ( Options.output_format == OFORMAT_COFF ) {
        q = (struct qdesc *)CurrSeg->e.seginfo->LinnumQueue;    // the problem seems to be here
        if ( q == NULL ) {
            q = LclAlloc( sizeof( struct qdesc ) );
            CurrSeg->e.seginfo->LinnumQueue = q;
            q->head = NULL;
        }
    } else
#endif
      q = 0;  // line 51 - insert q=0 so that q is always set by the line below:
        q = &LinnumQueue;



This line throws the exception:
((struct line_num_info *)q->tail)->next = data;

Shortly before, q->head changes its value ::)