I'm a developer working with a client to develop Metal C functions for their 
products. Up until recently I've defined __METAL_STATIC and linked with 
SCCR3BND. I decided recently to play with the dynamic library in LPALIB so I 
removed that #define. What I'm getting is compile errors on the substitution 
macros from metal.h. That is the first problem. I decided to try and circumvent 
the compile errors and I think I found a bug in the memcmp library function. 
That is the second problem. I'm really hoping someone will tell me I missed 
something really obvious or missed some maintenance.

I created a trivial sample program to demonstrate:

/*
  Sample for Metal C
*/

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
  char* xarg = "abcd";
  void *mem = malloc(64);
  memset(mem, 0x0f, 64);
  memcpy(mem, xarg, sizeof(xarg));
  int mcmp = memcmp(mem, xarg, sizeof(xarg));
  free(mem);
}
Of course, this compiles and runs just fine on Visual Studio where I do my 
initial development. On z/OS XLC though I get errors like the following:

    12       |  memset(mem, 0x0f, 64);                                          
                                |     12
    12       +  ((___MEMSET * ) ( (*(struct __cvt_s * __ptr32 * __ptr32)16) -> 
__cvtecvt -> __ecvtsdc -> __sdca\+     12
===========> 
....b...........a.................................................................................
*=ERROR===========> a - CCN3275 Unexpected text ')' encountered.
*=ERROR===========> b - CCN3045 Undeclared identifier ___MEMSET.
    12       +libv31 -> __libfunc[33] ))(mem, 0x0f, 64);                        
                                +     12
===========> 
.........................................c........................................................
*=ERROR===========> c - CCN3277 Syntax error: possible missing ')' or ','?

The header file include list is exactly what I expect:

                        1   /usr/include/metal/stdio.h
                        2   /usr/include/metal/metal.h
                        3   /usr/include/metal/stddef.h
                        4   /usr/include/metal/stdlib.h
                        5   /usr/include/metal/builtins.h

Looking through all of the layers in the metal.h header started me looking for 
aspirin. I decided to push forward as an exercise by defining my own structures 
to use the Metal C function vector. I already had many of the standard z/OS 
structures mapped and added my own mapping of sys_libv31_s with real function 
prototypes:

struct sys_libv31_s
{
  void (*_em_0)();
  int (*_em_abs)(int,int); // 1
  int (*_em_atoi)(char*); // 2
  long (*_em_atol)(char*); // 3
  long long (*_em_atoll)(char*); // 4
  void* (*_em_calloc)(size_t); // 5

And my own substitution macros to remove the metal.h definition and put in my 
own EMCALL reference:

#define EMCALL(_t, _n) (##_t)(*(CVTPTR->CVTECVT->ECVTSDC->sdcalibv31->_em_##_n))
#define em_0  EMCALL(void, em_0)
#undef abs // 1
#define abs EMCALL(int, abs)
#undef atoi // 2
#define atoi EMCALL(int atoi)
#undef atol // 3
#define atol EMCALL(long, atol)
#undef atoll // 4
#define atoll EMCALL(long long, atoll)
#undef calloc // 5
#define calloc EMCALL(void *, calloc)

I can't give you the whole thing as it is too much to extract from client 
proprietary material. Hopefully, this is enough to get the gist.

Now this is where I believe I found a bug in the memcmp function returning an 
invalid result and also a potential S0C4. With getting all of my code to 
compile I found things taking some weird code paths. I tracked it down to a 
memcmp and setup the code in the sample above to test it. I found the memcmp 
above returns an invalid result, 0x0f, even though the memory is equal. I went 
into TEST and disassembled the code and got this:


1F24CD78.    STM     R14,R3,12(R13)

1F24CD7C.    LR      R15,R13

1F24CD7E.    L       R13,8(,R13)

1F24CD82.    ST      R15,4(,R13)

1F24CD86.    STMH    R14,R3,80(R13)

1F24CD8C.    L       R14,0(,R1)

1F24CD90.    L       R2,4(,R1)

1F24CD94.    ICM     R0,15,8(R1)

1F24CD98.    BRC     8,*+52

1F24CD9C.    LR      R1,R0

1F24CD9E.    LLGC    R15,0(,R14)

1F24CDA4.    LLGC    R3,0(,R2)

1F24CDAA.    LA      R14,1(,R14)

1F24CDAE.    LA      R2,1(,R2)

1F24CDB2.    CR      R15,R3

1F24CDB4.    BRC     7,*+36

1F24CDB8.    LLGC    R15,0(,R14)

1F24CDBE.    LLGC    R3,0(,R2)

1F24CDC4.    BRCT    R1,*-26

1F24CDC8.    BRC     15,*+16

1F24CDCC.    LLGC    R15,0(,R14)

1F24CDD2.    LLGC    R3,0(,R2)

1F24CDD8.    SLR     R15,R3

1F24CDDA.    LMH     R14,R3,80(R13)

1F24CDE0.    L       R13,4(,R13)

1F24CDE4.    L       R14,12(,R13)

1F24CDE8.    LM      R1,R3,24(R13)

1F24CDEC.    BCR     15,R14

The important thing is that the loop uses R14 & R2 as the character pointers 
and R1 as the count. The loop at D9E loads the first bytes of each memory area. 
Then it increments the pointers, does the compare, and if NE branches to *+36 
(DCC). It then reloads R15 & R3 but the pointers have already been incremented. 
It calculates the difference of the two bytes as the return value. This gets 
the two random bytes after the memory area to compute the result which is an 
incorrout and a possible S0C4. Similarly, it uses those same next bytes if the 
result is BRC NE falls through giving random results and/or S0C4 if the strings 
are equal.

I thought I was totally delusional at this point since how could any code work 
if the memcmp library function was bad. Then I further found that 
metal/builtin.h overrides the library call and causes a fair number of these 
critical library functions to be inlined by the compiler which of course 
generates good code. I also verified that none of my old links with SCCR3BND 
pull in any of the library memory functions (memcmp, memcpy, etc.) along with a 
bunch of other stdlib functions which builtin.h overrides.

I'd be perfectly happy for someone to tell me I missed some obvious compiler 
option or did something else really stupid.


Dennis C. Fitzpatrick
[email protected]<mailto:[email protected]>
H: 630.325.6184
W: 630.325.6137
M: 630.660.8040


----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN

Reply via email to